From bb193325cc4e5af7d4e715072a242c1d3cfce26e Mon Sep 17 00:00:00 2001 From: InKryption <59504965+InKryption@users.noreply.github.com> Date: Mon, 22 Nov 2021 23:32:29 +0000 Subject: [PATCH 01/51] Add missing error to glfwGetClipboardString docs Add GLFW_FORMAT_UNAVAILABLE to the list of possible errors in the reference documentation for glfwGetClipboardString. Slightly edited by @elmindreda. Closes #1998 --- 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 751615eb..a1fa6f35 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -5792,8 +5792,8 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string); * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` * if an [error](@ref error_handling) occurred. * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_FORMAT_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. * * @pointer_lifetime The returned string is allocated and freed by GLFW. You * should not free it yourself. It is valid until the next call to @ref From a30cd6acef49a4527546fe15d490b705df959c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 25 Nov 2021 01:22:46 +0100 Subject: [PATCH 02/51] Add credit Related to #1998 --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 4190b261..d309e435 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -77,6 +77,7 @@ video tutorials. - Paul Holden - Warren Hu - Charles Huber + - InKryption - IntellectualKitty - Aaron Jacobs - Erik S. V. Jansson From eacc1cafba90fa7b52302841dd47f5f8b1bf777a Mon Sep 17 00:00:00 2001 From: luz paz Date: Thu, 28 Oct 2021 14:35:09 -0400 Subject: [PATCH 03/51] Fix source comment typo Closes #1982 --- examples/splitview.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/splitview.c b/examples/splitview.c index 4f0a8a98..990df12c 100644 --- a/examples/splitview.c +++ b/examples/splitview.c @@ -2,7 +2,7 @@ // This is an example program for the GLFW library // // The program uses a "split window" view, rendering four views of the -// same scene in one window (e.g. uesful for 3D modelling software). This +// same scene in one window (e.g. useful for 3D modelling software). This // demo uses scissors to separate the four different rendering areas from // each other. // From b3a98f855568b1a4f3961cfa30cb7a201fb91a40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Tue, 9 Nov 2021 19:40:36 +0100 Subject: [PATCH 04/51] Update comments for global mutable data --- src/init.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/init.c b/src/init.c index c4c5e030..b5c5da9c 100644 --- a/src/init.c +++ b/src/init.c @@ -36,16 +36,15 @@ #include -// The global variables below comprise all mutable global data in GLFW -// -// Any other global variable is a bug +// NOTE: The global variables below comprise all mutable global data in GLFW +// Any other mutable global variable is a bug -// Global state shared between compilation units of GLFW +// This contains all mutable state shared between compilation units of GLFW // _GLFWlibrary _glfw = { GLFW_FALSE }; // These are outside of _glfw so they can be used before initialization and -// after termination +// after termination without special handling when _glfw is cleared to zero // static _GLFWerror _glfwMainThreadError; static GLFWerrorfun _glfwErrorCallback; From 706d1f16535747e7889df26f3d639e9212e9ad5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Tue, 16 Nov 2021 01:51:27 +0100 Subject: [PATCH 05/51] Gather Null specific platform selection logic The more specific error description is now used whatever the desired platform is, when a binary only supports the Null platform. --- src/platform.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/platform.c b/src/platform.c index a692432d..d0bbd06d 100644 --- a/src/platform.c +++ b/src/platform.c @@ -72,6 +72,11 @@ GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform) // Only allow the Null platform if specifically requested if (desiredID == GLFW_PLATFORM_NULL) return _glfwConnectNull(desiredID, platform); + else if (count == 0) + { + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "This binary only supports the Null platform"); + return GLFW_FALSE; + } if (desiredID == GLFW_ANY_PLATFORM) { @@ -86,10 +91,7 @@ GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform) return GLFW_TRUE; } - if (count) - _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "Failed to detect any supported platform"); - else - _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "This binary only supports the Null platform"); + _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "Failed to detect any supported platform"); } else { From 37fc28bff6cad7164aa67e828e9317596f8080da Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Mon, 15 Nov 2021 15:50:37 -0700 Subject: [PATCH 06/51] Fix docs calling GLFW_CONTEXT_REVISION a hint This docstring previously indicated that GLFW_CONTEXT_REVISION was a window hint and attribute, but in fact it is only a window attribute (there is no code which uses this constant in any other context.) We noticed this in https://github.com/hexops/mach/pull/71/files#r749741814 Closes #1992 Signed-off-by: Stephen Gutekanst --- include/GLFW/glfw3.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index a1fa6f35..d76f5c49 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -1028,7 +1028,7 @@ extern "C" { * and [attribute](@ref GLFW_CONTEXT_VERSION_MINOR_attrib). */ #define GLFW_CONTEXT_VERSION_MINOR 0x00022003 -/*! @brief Context client API revision number hint and attribute. +/*! @brief Context client API revision number attribute. * * Context client API revision number * [attribute](@ref GLFW_CONTEXT_REVISION_attrib). From 9cd4d2fa204fc9fb884b9bb9096cedb7f1484cf7 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Sun, 31 Oct 2021 11:22:40 -0700 Subject: [PATCH 07/51] X11: Fix undefined behavior in glfwSetWindowIcon The conversion of window icon image data involves unsigned char color values being promoted to int and then shifted to the left by 24. For 32-bit ints this is just far enough to trigger undefined behavior. It worked by accident because of how current compilers translate this piece of code. This was caught by @slimsag while working on [Zig bindings for GLFW][1], and diagnosed together with @Andoryuuta, as described [in an article][2]. Zig has UBSan enabled by default, which caught this undefined behavior. [1]: https://github.com/hexops/mach-glfw [2]: https://devlog.hexops.com/2021/perfecting-glfw-for-zig-and-finding-undefined-behavior#finding-lurking-undefined-behavior-in-6-year-old-glfw-code Thanks to Maato, martinhath, dcousens, drfuchs and Validark for helping to refine the solution. This commit message was rewritten by @elmindreda to hopefully reflect the conclusions of the pull request thread. Related to hexops/mach#20 Closes #1986 --- src/x11_window.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/x11_window.c b/src/x11_window.c index 616f9fd8..ea775cd4 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -2105,8 +2105,8 @@ void _glfwSetWindowIconX11(_GLFWwindow* window, int count, const GLFWimage* imag for (int i = 0; i < count; i++) longCount += 2 + images[i].width * images[i].height; - long* icon = _glfw_calloc(longCount, sizeof(long)); - long* target = icon; + unsigned long* icon = _glfw_calloc(longCount, sizeof(unsigned long)); + unsigned long* target = icon; for (int i = 0; i < count; i++) { @@ -2115,13 +2115,20 @@ void _glfwSetWindowIconX11(_GLFWwindow* window, int count, const GLFWimage* imag for (int j = 0; j < images[i].width * images[i].height; j++) { - *target++ = (images[i].pixels[j * 4 + 0] << 16) | - (images[i].pixels[j * 4 + 1] << 8) | - (images[i].pixels[j * 4 + 2] << 0) | - (images[i].pixels[j * 4 + 3] << 24); + *target++ = (((unsigned long)images[i].pixels[j * 4 + 0]) << 16) | + (((unsigned long)images[i].pixels[j * 4 + 1]) << 8) | + (((unsigned long)images[i].pixels[j * 4 + 2]) << 0) | + (((unsigned long)images[i].pixels[j * 4 + 3]) << 24); } } + // Important: Despite XChangeProperty docs indicating that `icon` (unsigned char*) would be + // in the format of the icon image, e.g. 32-bit below, the function actually casts the ptr + // (unsigned char*) internally to (long*) and then if long is defined as 64-bits, as on IL64 + // platforms, extracts only 32 bits from the long leaving the other 32 unused. That is, on a + // 64-bit platform XChangeProperty expects 64-bit integers representing 32-bit pixels. + // + // See https://github.com/glfw/glfw/pull/1986#issuecomment-962445299 XChangeProperty(_glfw.x11.display, window->x11.handle, _glfw.x11.NET_WM_ICON, XA_CARDINAL, 32, From e40fa3bb94a9277d7190ec49e197de663eb943bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Tue, 2 Nov 2021 23:15:05 +0100 Subject: [PATCH 08/51] Add credits and update changelog --- CONTRIBUTORS.md | 2 ++ README.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index d309e435..959b55eb 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -68,6 +68,8 @@ video tutorials. - Kovid Goyal - Eloi Marín Gratacós - Stefan Gustavson + - Andrew Gutekanst + - Stephen Gutekanst - Jonathan Hale - hdf89shfdfs - Sylvain Hellegouarch diff --git a/README.md b/README.md index d9257e58..b13739f1 100644 --- a/README.md +++ b/README.md @@ -259,6 +259,8 @@ information on what to include when reporting a bug. - [X11] Bugfix: Some window attributes were not applied on leaving fullscreen (#1863) - [X11] Bugfix: Changing `GLFW_FLOATING` could leak memory + - [X11] Bugfix: Icon pixel format conversion worked only by accident, relying on + undefined behavior (#1986) - [Wayland] Added dynamic loading of all Wayland libraries - [Wayland] Removed support for `wl_shell` (#1443) - [Wayland] Bugfix: The `GLFW_HAND_CURSOR` shape used the wrong image (#1432) From 79de08db06d358c4aae243532d2e530e62780687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Tue, 30 Nov 2021 20:34:47 +0100 Subject: [PATCH 09/51] Cleanup --- src/x11_window.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/x11_window.c b/src/x11_window.c index ea775cd4..a5255215 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -2115,20 +2115,19 @@ void _glfwSetWindowIconX11(_GLFWwindow* window, int count, const GLFWimage* imag for (int j = 0; j < images[i].width * images[i].height; j++) { - *target++ = (((unsigned long)images[i].pixels[j * 4 + 0]) << 16) | - (((unsigned long)images[i].pixels[j * 4 + 1]) << 8) | - (((unsigned long)images[i].pixels[j * 4 + 2]) << 0) | - (((unsigned long)images[i].pixels[j * 4 + 3]) << 24); + *target++ = (((unsigned long) images[i].pixels[j * 4 + 0]) << 16) | + (((unsigned long) images[i].pixels[j * 4 + 1]) << 8) | + (((unsigned long) images[i].pixels[j * 4 + 2]) << 0) | + (((unsigned long) images[i].pixels[j * 4 + 3]) << 24); } } - // Important: Despite XChangeProperty docs indicating that `icon` (unsigned char*) would be - // in the format of the icon image, e.g. 32-bit below, the function actually casts the ptr - // (unsigned char*) internally to (long*) and then if long is defined as 64-bits, as on IL64 - // platforms, extracts only 32 bits from the long leaving the other 32 unused. That is, on a - // 64-bit platform XChangeProperty expects 64-bit integers representing 32-bit pixels. - // - // See https://github.com/glfw/glfw/pull/1986#issuecomment-962445299 + // NOTE: XChangeProperty expects 32-bit values like the image data above to be + // placed in the 32 least significant bits of individual longs. This is + // true even if long is 64-bit and a WM protocol calls for "packed" data. + // This is because of a historical mistake that then became part of the Xlib + // ABI. Xlib will pack these values into a regular array of 32-bit values + // before sending it over the wire. XChangeProperty(_glfw.x11.display, window->x11.handle, _glfw.x11.NET_WM_ICON, XA_CARDINAL, 32, From d1efa3298345a36a969f1fbbb2272d97ad5354af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Tue, 30 Nov 2021 21:14:44 +0100 Subject: [PATCH 10/51] Formatting --- src/win32_window.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/win32_window.c b/src/win32_window.c index ae7710a2..9fb0baa1 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -1645,8 +1645,7 @@ void _glfwGetWindowFrameSizeWin32(_GLFWwindow* window, *bottom = rect.bottom - height; } -void _glfwGetWindowContentScaleWin32(_GLFWwindow* window, - float* xscale, float* yscale) +void _glfwGetWindowContentScaleWin32(_GLFWwindow* window, float* xscale, float* yscale) { const HANDLE handle = MonitorFromWindow(window->win32.handle, MONITOR_DEFAULTTONEAREST); From fbfd7e65c842c7909b11747f0641364593304f1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 1 Dec 2021 17:55:16 +0100 Subject: [PATCH 11/51] Win32: Fix bad content scale on monitor disconnect The monitor handle could have become invalid just before the call to GetDpiForMonitor. It was possible for both window and monitor content scale queries. This ensures both that an appropriate error is emitted and that the retrieved values are zero on error. Fixes #1615 --- CONTRIBUTORS.md | 1 + README.md | 3 +++ src/win32_monitor.c | 13 ++++++++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 959b55eb..d86fe473 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -62,6 +62,7 @@ video tutorials. - Mário Freitas - GeO4d - Marcus Geelnard + - ghuser404 - Charles Giessen - Ryan C. Gordon - Stephen Gowen diff --git a/README.md b/README.md index b13739f1..e3f7d9e7 100644 --- a/README.md +++ b/README.md @@ -202,6 +202,9 @@ information on what to include when reporting a bug. later (#1783,#1796) - [Win32] Bugfix: Compilation with LLVM for Windows failed (#1807,#1824,#1874) - [Win32] Bugfix: The foreground lock timeout was overridden, ignoring the user + - [Win32] Bugfix: Content scale queries could fail silently (#1615) + - [Win32] Bugfix: Content scales could have garbage values if monitor was recently + disconnected (#1615) - [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_monitor.c b/src/win32_monitor.c index 17359a5f..cdee49a9 100644 --- a/src/win32_monitor.c +++ b/src/win32_monitor.c @@ -317,8 +317,19 @@ void _glfwGetHMONITORContentScaleWin32(HMONITOR handle, float* xscale, float* ys { UINT xdpi, ydpi; + if (xscale) + *xscale = 0.f; + if (yscale) + *yscale = 0.f; + if (IsWindows8Point1OrGreater()) - GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi); + { + if (GetDpiForMonitor(handle, MDT_EFFECTIVE_DPI, &xdpi, &ydpi) != S_OK) + { + _glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to query monitor DPI"); + return; + } + } else { const HDC dc = GetDC(NULL); From 53d86c64d709ff52886580d338d9b3b2b1f27266 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 1 Dec 2021 18:09:56 +0100 Subject: [PATCH 12/51] Win32: Handle content scale error on creation Only apply the content scale to the initial size of the window if content scale retrieval succeeded. Related to #1615. --- src/win32_window.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/win32_window.c b/src/win32_window.c index 9fb0baa1..e03b8564 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -1304,8 +1304,12 @@ static int createNativeWindow(_GLFWwindow* window, { float xscale, yscale; _glfwGetWindowContentScaleWin32(window, &xscale, &yscale); - rect.right = (int) (rect.right * xscale); - rect.bottom = (int) (rect.bottom * yscale); + + if (xscale > 0.f && yscale > 0.f) + { + rect.right = (int) (rect.right * xscale); + rect.bottom = (int) (rect.bottom * yscale); + } } ClientToScreen(window->win32.handle, (POINT*) &rect.left); From c19f36b28d255d280d39446f09f36f441318138e Mon Sep 17 00:00:00 2001 From: InKryption <59504965+InKryption@users.noreply.github.com> Date: Sun, 5 Dec 2021 17:51:43 +0100 Subject: [PATCH 13/51] Add missing errors section for glfwGetGamepadName The reference documentation for glfwGetGamepadName lacked the possible errors section. Closes #2007 --- include/GLFW/glfw3.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index d76f5c49..f0b8d5ec 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -5703,6 +5703,8 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string); * joystick is not present, does not have a mapping or an * [error](@ref error_handling) occurred. * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref GLFW_INVALID_ENUM. + * * @pointer_lifetime The returned string is allocated and freed by GLFW. You * should not free it yourself. It is valid until the specified joystick is * disconnected, the gamepad mappings are updated or the library is terminated. From cd01187b9d4145a3947f806f113bc777c3aa4c1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 8 Dec 2021 23:09:59 +0100 Subject: [PATCH 14/51] Fix initial windowed mode size for test --- tests/iconify.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/iconify.c b/tests/iconify.c index e5a428a0..32fd44f2 100644 --- a/tests/iconify.c +++ b/tests/iconify.c @@ -38,7 +38,7 @@ #include "getopt.h" -static int windowed_xpos, windowed_ypos, windowed_width, windowed_height; +static int windowed_xpos, windowed_ypos, windowed_width = 640, windowed_height = 480; static void usage(void) { @@ -181,8 +181,8 @@ static GLFWwindow* create_window(GLFWmonitor* monitor) } else { - width = 640; - height = 480; + width = windowed_width; + height = windowed_height; } window = glfwCreateWindow(width, height, "Iconify", monitor, NULL); From 900848ad0ce0c94a5d4cb8e0ac2489ff11973477 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 9 Dec 2021 19:35:15 +0100 Subject: [PATCH 15/51] X11: Add extension header paths to CMake target The way the X11 find module is written, these paths can differ from the base X11 header path, even if they very rarely do. Fixes #1999 --- src/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a0be580e..16cb1749 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -194,31 +194,37 @@ if (GLFW_BUILD_X11) if (NOT X11_Xrandr_INCLUDE_PATH) message(FATAL_ERROR "RandR headers not found; install libxrandr development package") endif() + target_include_directories(glfw PRIVATE "${X11_Xrandr_INCLUDE_PATH}") # Check for Xinerama (legacy multi-monitor support) if (NOT X11_Xinerama_INCLUDE_PATH) message(FATAL_ERROR "Xinerama headers not found; install libxinerama development package") endif() + target_include_directories(glfw PRIVATE "${X11_Xinerama_INCLUDE_PATH}") # Check for Xkb (X keyboard extension) if (NOT X11_Xkb_INCLUDE_PATH) message(FATAL_ERROR "XKB headers not found; install X11 development package") endif() + target_include_directories(glfw PRIVATE "${X11_Xkb_INCLUDE_PATH}") # Check for Xcursor (cursor creation from RGBA images) if (NOT X11_Xcursor_INCLUDE_PATH) message(FATAL_ERROR "Xcursor headers not found; install libxcursor development package") endif() + target_include_directories(glfw PRIVATE "${X11_Xcursor_INCLUDE_PATH}") # Check for XInput (modern HID input) if (NOT X11_Xi_INCLUDE_PATH) message(FATAL_ERROR "XInput headers not found; install libxi development package") endif() + target_include_directories(glfw PRIVATE "${X11_Xi_INCLUDE_PATH}") # Check for X Shape (custom window input shape) if (NOT X11_Xshape_INCLUDE_PATH) message(FATAL_ERROR "X Shape headers not found; install libxext development package") endif() + target_include_directories(glfw PRIVATE "${X11_Xshape_INCLUDE_PATH}") endif() if (UNIX AND NOT APPLE) From 963e728881d7551aab0b843c79915f2419d4d36e Mon Sep 17 00:00:00 2001 From: Stone Tickle Date: Fri, 5 Jun 2020 12:51:25 +0900 Subject: [PATCH 16/51] Wayland: Set O_NONBLOCK on repeat timerfd Fixes #1710 Fixes #1711 --- src/wl_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wl_init.c b/src/wl_init.c index acfe477d..bba908fa 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -1336,7 +1336,7 @@ int _glfwInitWayland(void) _glfw.wl.timerfd = -1; if (_glfw.wl.seatVersion >= 4) - _glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + _glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); if (!_glfw.wl.wmBase) { @@ -1370,7 +1370,7 @@ int _glfwInitWayland(void) wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm); _glfw.wl.cursorSurface = wl_compositor_create_surface(_glfw.wl.compositor); - _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); } if (_glfw.wl.seat && _glfw.wl.dataDeviceManager) From 68879081cb39f50bd65d12e0f1869f5970dc71b9 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 14 Dec 2021 09:29:01 +0100 Subject: [PATCH 17/51] =?UTF-8?q?Wayland:=20Continue=20poll()=20if=20timer?= =?UTF-8?q?fd=20can=E2=80=99t=20be=20read?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the case the key repeat timerfd was interrupted before read(), the cursor timerfd wasn’t read at all even when it could. Related to #1711 --- README.md | 1 + src/wl_window.c | 11 +++-------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index e3f7d9e7..57c43a4b 100644 --- a/README.md +++ b/README.md @@ -278,6 +278,7 @@ information on what to include when reporting a bug. - [Wayland] Bugfix: Some keys were not repeating in Wayland (#1908) - [Wayland] Bugfix: Non-arrow cursors are offset from the hotspot (#1706,#1899) - [Wayland] Bugfix: The `O_CLOEXEC` flag was not defined on FreeBSD + - [Wayland] Bugfix: Key repeat could lead to a race condition (#1710) - [POSIX] Removed use of deprecated function `gettimeofday` - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled - [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072) diff --git a/src/wl_window.c b/src/wl_window.c index b4c59d69..8ed803b4 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -751,10 +751,7 @@ static void handleEvents(int timeout) if (fds[1].revents & POLLIN) { read_ret = read(_glfw.wl.timerfd, &repeats, sizeof(repeats)); - if (read_ret != 8) - return; - - if (_glfw.wl.keyboardFocus) + if (read_ret == 8 && _glfw.wl.keyboardFocus) { for (uint64_t i = 0; i < repeats; ++i) { @@ -770,10 +767,8 @@ static void handleEvents(int timeout) if (fds[2].revents & POLLIN) { read_ret = read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)); - if (read_ret != 8) - return; - - incrementCursorImage(_glfw.wl.pointerFocus); + if (read_ret == 8) + incrementCursorImage(_glfw.wl.pointerFocus); } } else From 6281f498c875f49d8ac5c5a02d968fb1792fd9f5 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 14 Dec 2021 18:35:30 +0100 Subject: [PATCH 18/51] EGL: Use EGL_EXT_present_opaque when available This extensions allows GLFW to instruct the driver to ignore the alpha bits, even in formats which contain them. This makes it possible to use the alpha bits as extra storage, without it affecting the end result getting displayed to the user. Fixes #1434 Fixes #1803 --- src/egl_context.c | 5 +++++ src/internal.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/egl_context.c b/src/egl_context.c index 03c72d04..edb2fae2 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -472,6 +472,8 @@ GLFWbool _glfwInitEGL(void) extensionSupportedEGL("EGL_KHR_get_all_proc_addresses"); _glfw.egl.KHR_context_flush_control = extensionSupportedEGL("EGL_KHR_context_flush_control"); + _glfw.egl.EXT_present_opaque = + extensionSupportedEGL("EGL_EXT_present_opaque"); return GLFW_TRUE; } @@ -646,6 +648,9 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, if (!fbconfig->doublebuffer) setAttrib(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER); + if (_glfw.egl.EXT_present_opaque) + setAttrib(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent); + setAttrib(EGL_NONE, EGL_NONE); native = _glfw.platform.getEGLNativeWindow(window); diff --git a/src/internal.h b/src/internal.h index c853ad9b..2a8c8d6d 100644 --- a/src/internal.h +++ b/src/internal.h @@ -177,6 +177,7 @@ typedef const GLubyte* (APIENTRY * PFNGLGETSTRINGIPROC)(GLenum,GLuint); #define EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x2098 #define EGL_PLATFORM_X11_EXT 0x31d5 #define EGL_PLATFORM_WAYLAND_EXT 0x31d8 +#define EGL_PRESENT_OPAQUE_EXT 0x31df #define EGL_PLATFORM_ANGLE_ANGLE 0x3202 #define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203 #define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320d @@ -803,6 +804,7 @@ struct _GLFWlibrary GLFWbool EXT_platform_base; GLFWbool EXT_platform_x11; GLFWbool EXT_platform_wayland; + GLFWbool EXT_present_opaque; GLFWbool ANGLE_platform_angle; GLFWbool ANGLE_platform_angle_opengl; GLFWbool ANGLE_platform_angle_d3d; From c2f0a0ae5990a23d84c3f4529771b1268a34f918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 22 Dec 2021 14:16:19 +0100 Subject: [PATCH 19/51] Wayland: Fix duplicate focus event on activation --- README.md | 1 + src/wl_window.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 57c43a4b..4a0faf35 100644 --- a/README.md +++ b/README.md @@ -279,6 +279,7 @@ information on what to include when reporting a bug. - [Wayland] Bugfix: Non-arrow cursors are offset from the hotspot (#1706,#1899) - [Wayland] Bugfix: The `O_CLOEXEC` flag was not defined on FreeBSD - [Wayland] Bugfix: Key repeat could lead to a race condition (#1710) + - [Wayland] Bugfix: Activating a window would emit two input focus events - [POSIX] Removed use of deprecated function `gettimeofday` - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled - [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072) diff --git a/src/wl_window.c b/src/wl_window.c index 8ed803b4..12af2701 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -537,7 +537,6 @@ static void xdgToplevelHandleConfigure(void* data, } if (fullscreen && activated) window->wl.wasFullscreen = GLFW_TRUE; - _glfwInputWindowFocus(window, activated); } static void xdgToplevelHandleClose(void* data, From e24fe4b189d2cf99e0374992e7fc6650f4c6cf01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 22 Dec 2021 14:19:55 +0100 Subject: [PATCH 20/51] Wayland: Fix key repeat continuing when refocused If a window lost input focus while a key was held down, the key repeat mechanism would resume once the window regained focus. --- README.md | 1 + src/wl_init.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/README.md b/README.md index 4a0faf35..2f505c00 100644 --- a/README.md +++ b/README.md @@ -280,6 +280,7 @@ information on what to include when reporting a bug. - [Wayland] Bugfix: The `O_CLOEXEC` flag was not defined on FreeBSD - [Wayland] Bugfix: Key repeat could lead to a race condition (#1710) - [Wayland] Bugfix: Activating a window would emit two input focus events + - [Wayland] Bugfix: Disable key repeat mechanism when window loses input focus - [POSIX] Removed use of deprecated function `gettimeofday` - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled - [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072) diff --git a/src/wl_init.c b/src/wl_init.c index bba908fa..fd6efaa8 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -508,6 +508,9 @@ static void keyboardHandleLeave(void* data, _glfw.wl.serial = serial; _glfw.wl.keyboardFocus = NULL; _glfwInputWindowFocus(window, GLFW_FALSE); + + struct itimerspec timer = {}; + timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL); } static int toGLFWKeyCode(uint32_t key) From 094aa6d3c721397825cb1095c156353463ecafb5 Mon Sep 17 00:00:00 2001 From: Jason Francis Date: Sun, 12 Jul 2020 20:47:50 -0400 Subject: [PATCH 21/51] Wayland: Fix window hiding Corrects the protocol violation when creating an xdg_surface from a wl_surface that already has a buffer due to EGL buffer swaps. This commit is based on PR #1731 by @ghost, but adapted and altered: - The XDG surface and role are now only created when a window is shown to prevent application lists from showing command-line applications with off-screen-only windows - The special case of Wayland+EGL buffer swap is now in the EGL code to mirror how X11 is handled - Adaption to run-time platform selection and separate credits file Fixes #1492 Closes #1731 --- CONTRIBUTORS.md | 1 + README.md | 1 + src/egl_context.c | 9 +++++++++ src/wl_window.c | 30 +++++++++--------------------- 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index d86fe473..1bfc5bc5 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -58,6 +58,7 @@ video tutorials. - Ahmad Fatoum - Felipe Ferreira - Michael Fogleman + - Jason Francis - Gerald Franz - Mário Freitas - GeO4d diff --git a/README.md b/README.md index 2f505c00..63e9f6bd 100644 --- a/README.md +++ b/README.md @@ -281,6 +281,7 @@ information on what to include when reporting a bug. - [Wayland] Bugfix: Key repeat could lead to a race condition (#1710) - [Wayland] Bugfix: Activating a window would emit two input focus events - [Wayland] Bugfix: Disable key repeat mechanism when window loses input focus + - [Wayland] Bugfix: Window hiding and showing did not work (#1492,#1731) - [POSIX] Removed use of deprecated function `gettimeofday` - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled - [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072) diff --git a/src/egl_context.c b/src/egl_context.c index edb2fae2..319da273 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -231,6 +231,15 @@ static void swapBuffersEGL(_GLFWwindow* window) return; } +#if defined(_GLFW_WAYLAND) + if (_glfw.platform.platformID == GLFW_PLATFORM_WAYLAND) + { + // NOTE: Swapping buffers on a hidden window on Wayland makes it visible + if (!window->wl.visible) + return; + } +#endif + eglSwapBuffers(_glfw.egl.display, window->context.egl.surface); } diff --git a/src/wl_window.c b/src/wl_window.c index 12af2701..10d0e25f 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -812,20 +812,6 @@ int _glfwCreateWindowWayland(_GLFWwindow* window, if (wndconfig->title) window->wl.title = _glfw_strdup(wndconfig->title); - if (wndconfig->visible) - { - if (!createXdgSurface(window)) - return GLFW_FALSE; - - window->wl.visible = GLFW_TRUE; - } - else - { - window->wl.xdg.surface = NULL; - window->wl.xdg.toplevel = NULL; - window->wl.visible = GLFW_FALSE; - } - window->wl.currentCursor = NULL; window->wl.monitors = _glfw_calloc(1, sizeof(_GLFWmonitor*)); @@ -1018,21 +1004,23 @@ void _glfwShowWindowWayland(_GLFWwindow* window) { if (!window->wl.visible) { - createXdgSurface(window); + // NOTE: The XDG surface and role are created here so command-line applications + // with off-screen windows do not appear in for example the Unity dock + if (!window->wl.xdg.toplevel) + createXdgSurface(window); + window->wl.visible = GLFW_TRUE; } } void _glfwHideWindowWayland(_GLFWwindow* window) { - if (window->wl.xdg.toplevel) + if (window->wl.visible) { - xdg_toplevel_destroy(window->wl.xdg.toplevel); - xdg_surface_destroy(window->wl.xdg.surface); - window->wl.xdg.toplevel = NULL; - window->wl.xdg.surface = NULL; + window->wl.visible = GLFW_FALSE; + wl_surface_attach(window->wl.surface, NULL, 0, 0); + wl_surface_commit(window->wl.surface); } - window->wl.visible = GLFW_FALSE; } void _glfwRequestWindowAttentionWayland(_GLFWwindow* window) From f8ef3ca719eba800232eff30f08885d69c564e86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 22 Dec 2021 18:52:30 +0100 Subject: [PATCH 22/51] Add hiding and showing to interactive window test --- tests/window.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/window.c b/tests/window.c index 3e2bc671..83baff46 100644 --- a/tests/window.c +++ b/tests/window.c @@ -121,7 +121,7 @@ int main(int argc, char** argv) nk_glfw3_new_frame(); if (nk_begin(nk, "main", area, 0)) { - nk_layout_row_dynamic(nk, 30, 4); + nk_layout_row_dynamic(nk, 30, 5); if (nk_button_label(nk, "Toggle Fullscreen")) { @@ -149,6 +149,16 @@ int main(int argc, char** argv) glfwIconifyWindow(window); if (nk_button_label(nk, "Restore")) glfwRestoreWindow(window); + if (nk_button_label(nk, "Hide (briefly)")) + { + glfwHideWindow(window); + + const double time = glfwGetTime() + 3.0; + while (glfwGetTime() < time) + glfwWaitEventsTimeout(1.0); + + glfwShowWindow(window); + } nk_layout_row_dynamic(nk, 30, 1); From 7d060ba4f1237c87ed53e007db619da8c25df282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 22 Dec 2021 22:19:25 +0100 Subject: [PATCH 23/51] X11: Fix sonames for loaded libraries on OpenBSD The OpenBSD ports tree assigns its own soname version numbers, so the hardcoded sonames GLFW uses to load libraries on non-macOS Unices are often incorrect. Instead OpenBSD recommends that run-time loading should leave out the version numbers entirely. The OpenBSD ld.so then finds the correct library. This upstreams the ports tree fixes for Xcursor and EGL, and adds the corresponding fix for all other run-time loaded library sonames. Tested on OpenBSD 7.0. This issue was initially reported on IRC. --- README.md | 1 + src/egl_context.c | 8 ++++++++ src/glx_context.c | 2 ++ src/osmesa_context.c | 2 ++ src/vulkan.c | 2 ++ src/x11_init.c | 20 ++++++++++++++++++++ 6 files changed, 35 insertions(+) diff --git a/README.md b/README.md index 63e9f6bd..9641fdf2 100644 --- a/README.md +++ b/README.md @@ -264,6 +264,7 @@ information on what to include when reporting a bug. - [X11] Bugfix: Changing `GLFW_FLOATING` could leak memory - [X11] Bugfix: Icon pixel format conversion worked only by accident, relying on undefined behavior (#1986) + - [X11] Bugfix: Dynamic loading on OpenBSD failed due to soname differences - [Wayland] Added dynamic loading of all Wayland libraries - [Wayland] Removed support for `wl_shell` (#1443) - [Wayland] Bugfix: The `GLFW_HAND_CURSOR` shape used the wrong image (#1432) diff --git a/src/egl_context.c b/src/egl_context.c index 319da273..89ea78fa 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -325,6 +325,8 @@ GLFWbool _glfwInitEGL(void) "libEGL.dylib", #elif defined(__CYGWIN__) "libEGL-1.so", +#elif defined(__OpenBSD__) + "libEGL.so", #else "libEGL.so.1", #endif @@ -700,6 +702,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, "libGLES_CM.dll", #elif defined(_GLFW_COCOA) "libGLESv1_CM.dylib", +#elif defined(__OpenBSD__) + "libGLESv1_CM.so", #else "libGLESv1_CM.so.1", "libGLES_CM.so.1", @@ -717,6 +721,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, "libGLESv2.dylib", #elif defined(__CYGWIN__) "libGLESv2-2.so", +#elif defined(__OpenBSD__) + "libGLESv2.so", #else "libGLESv2.so.2", #endif @@ -728,6 +734,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, _GLFW_OPENGL_LIBRARY, #elif defined(_GLFW_WIN32) #elif defined(_GLFW_COCOA) +#elif defined(__OpenBSD__) + "libGL.so", #else "libGL.so.1", #endif diff --git a/src/glx_context.c b/src/glx_context.c index 060e487d..31cd34dc 100644 --- a/src/glx_context.c +++ b/src/glx_context.c @@ -259,6 +259,8 @@ GLFWbool _glfwInitGLX(void) _GLFW_GLX_LIBRARY, #elif defined(__CYGWIN__) "libGL-1.so", +#elif defined(__OpenBSD__) + "libGL.so", #else "libGL.so.1", "libGL.so", diff --git a/src/osmesa_context.c b/src/osmesa_context.c index 1b28c517..161d9fd8 100644 --- a/src/osmesa_context.c +++ b/src/osmesa_context.c @@ -124,6 +124,8 @@ GLFWbool _glfwInitOSMesa(void) "libOSMesa.8.dylib", #elif defined(__CYGWIN__) "libOSMesa-8.so", +#elif defined(__OpenBSD__) + "libOSMesa.so", #else "libOSMesa.so.8", "libOSMesa.so.6", diff --git a/src/vulkan.c b/src/vulkan.c index 2a64ecb4..f02b1ede 100644 --- a/src/vulkan.c +++ b/src/vulkan.c @@ -63,6 +63,8 @@ GLFWbool _glfwInitVulkan(int mode) _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib"); if (!_glfw.vk.handle) _glfw.vk.handle = _glfwLoadLocalVulkanLoaderCocoa(); +#elif defined(__OpenBSD__) + _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so"); #else _glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so.1"); #endif diff --git a/src/x11_init.c b/src/x11_init.c index 68d6a6c4..acfa7933 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -601,7 +601,11 @@ static void detectEWMH(void) // static GLFWbool initExtensions(void) { +#if defined(__OpenBSD__) + _glfw.x11.vidmode.handle = _glfwPlatformLoadModule("libXxf86vm.so"); +#else _glfw.x11.vidmode.handle = _glfwPlatformLoadModule("libXxf86vm.so.1"); +#endif if (_glfw.x11.vidmode.handle) { _glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension) @@ -621,6 +625,8 @@ static GLFWbool initExtensions(void) #if defined(__CYGWIN__) _glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi-6.so"); +#elif defined(__OpenBSD__) + _glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi.so"); #else _glfw.x11.xi.handle = _glfwPlatformLoadModule("libXi.so.6"); #endif @@ -651,6 +657,8 @@ static GLFWbool initExtensions(void) #if defined(__CYGWIN__) _glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr-2.so"); +#elif defined(__OpenBSD__) + _glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr.so"); #else _glfw.x11.randr.handle = _glfwPlatformLoadModule("libXrandr.so.2"); #endif @@ -743,6 +751,8 @@ static GLFWbool initExtensions(void) #if defined(__CYGWIN__) _glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor-1.so"); +#elif defined(__OpenBSD__) + _glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor.so"); #else _glfw.x11.xcursor.handle = _glfwPlatformLoadModule("libXcursor.so.1"); #endif @@ -764,6 +774,8 @@ static GLFWbool initExtensions(void) #if defined(__CYGWIN__) _glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama-1.so"); +#elif defined(__OpenBSD__) + _glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama.so"); #else _glfw.x11.xinerama.handle = _glfwPlatformLoadModule("libXinerama.so.1"); #endif @@ -817,6 +829,8 @@ static GLFWbool initExtensions(void) { #if defined(__CYGWIN__) _glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb-1.so"); +#elif defined(__OpenBSD__) + _glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb.so"); #else _glfw.x11.x11xcb.handle = _glfwPlatformLoadModule("libX11-xcb.so.1"); #endif @@ -830,6 +844,8 @@ static GLFWbool initExtensions(void) #if defined(__CYGWIN__) _glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender-1.so"); +#elif defined(__OpenBSD__) + _glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender.so"); #else _glfw.x11.xrender.handle = _glfwPlatformLoadModule("libXrender.so.1"); #endif @@ -857,6 +873,8 @@ static GLFWbool initExtensions(void) #if defined(__CYGWIN__) _glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext-6.so"); +#elif defined(__OpenBSD__) + _glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext.so"); #else _glfw.x11.xshape.handle = _glfwPlatformLoadModule("libXext.so.6"); #endif @@ -1203,6 +1221,8 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform) #if defined(__CYGWIN__) void* module = _glfwPlatformLoadModule("libX11-6.so"); +#elif defined(__OpenBSD__) + void* module = _glfwPlatformLoadModule("libX11.so"); #else void* module = _glfwPlatformLoadModule("libX11.so.6"); #endif From 05b0e2fab2be38e0c937bf2ba09f6dc892160616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Sun, 26 Dec 2021 18:02:00 +0100 Subject: [PATCH 24/51] Update docs for specific Vulkan surface extensions Related to #2014 --- include/GLFW/glfw3.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index f0b8d5ec..520dc1df 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -6189,9 +6189,6 @@ GLFWAPI int glfwVulkanSupported(void); * returned array, as it is an error to specify an extension more than once in * the `VkInstanceCreateInfo` struct. * - * @remark @macos GLFW currently supports both the `VK_MVK_macos_surface` and - * the newer `VK_EXT_metal_surface` extensions. - * * @pointer_lifetime The returned array is allocated and freed by GLFW. You * should not free it yourself. It is guaranteed to be valid only until the * library is terminated. @@ -6330,17 +6327,20 @@ GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhys * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should * eliminate almost all occurrences of these errors. * - * @remark @macos This function currently only supports the - * `VK_MVK_macos_surface` extension from MoltenVK. + * @remark @macos GLFW prefers the `VK_EXT_metal_surface` extension, with the + * `VK_MVK_macos_surface` extension as a fallback. The name of the selected + * extension, if any, is included in the array returned by @ref + * glfwGetRequiredInstanceExtensions. * * @remark @macos This function creates and sets a `CAMetalLayer` instance for * the window content view, which is required for MoltenVK to function. * - * @remark @x11 GLFW by default attempts to use the `VK_KHR_xcb_surface` - * extension, if available. You can make it prefer the `VK_KHR_xlib_surface` - * extension by setting the + * @remark @x11 By default GLFW prefers the `VK_KHR_xcb_surface` extension, + * with the `VK_KHR_xlib_surface` extension as a fallback. You can make + * `VK_KHR_xlib_surface` the preferred extension by setting the * [GLFW_X11_XCB_VULKAN_SURFACE](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint) init - * hint. + * hint. The name of the selected extension, if any, is included in the array + * returned by @ref glfwGetRequiredInstanceExtensions. * * @thread_safety This function may be called from any thread. For * synchronization details of Vulkan objects, see the Vulkan specification. From 8edbc4971d6c994d84f12f349afdeef41fae527f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Mon, 27 Dec 2021 01:31:38 +0100 Subject: [PATCH 25/51] Wayland: Document delayed window showing --- include/GLFW/glfw3.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 520dc1df..72d5fa71 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -3764,6 +3764,11 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * GLFW_PLATFORM_ERROR. * + * @remark @wayland Because Wayland wants every frame of the desktop to be + * complete, this function does not immediately make the window visible. + * Instead it will become visible the next time the window framebuffer is + * updated after this call. + * * @thread_safety This function must only be called from the main thread. * * @sa @ref window_hide From 855d338a6596cef6b88b298ad00b6f2658019877 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Thu, 30 Dec 2021 19:04:10 +0100 Subject: [PATCH 26/51] Wayland: Use correct action on fallback decoration We were previously storing the pointer position only when on the main window, so when the user clicked on a fallback decoration it would use the last position of the cursor on the main window, instead of the position in the decoration surface. Fixes part of #1991. --- src/wl_init.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/wl_init.c b/src/wl_init.c index fd6efaa8..d26e5f6c 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -207,12 +207,12 @@ static void pointerHandleMotion(void* data, return; x = wl_fixed_to_double(sx); y = wl_fixed_to_double(sy); + window->wl.cursorPosX = x; + window->wl.cursorPosY = y; switch (window->wl.decorations.focus) { case mainWindow: - window->wl.cursorPosX = x; - window->wl.cursorPosY = y; _glfwInputCursorPos(window, x, y); _glfw.wl.cursorPreviousName = NULL; return; @@ -272,9 +272,7 @@ static void pointerHandleButton(void* data, if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP; else - { xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial); - } break; case leftDecoration: if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) @@ -303,6 +301,7 @@ static void pointerHandleButton(void* data, { xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat, serial, edges); + return; } } else if (button == BTN_RIGHT) From 79e7e65c9d6145ded05baf54f82b53f5df451ea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Sun, 26 Dec 2021 22:01:32 +0100 Subject: [PATCH 27/51] Wayland: Clean up event pump Adapt style to the rest of the project. --- src/wl_window.c | 59 ++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index 10d0e25f..d51c9309 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -708,22 +708,19 @@ static void incrementCursorImage(_GLFWwindow* window) static void handleEvents(int timeout) { - struct wl_display* display = _glfw.wl.display; - struct pollfd fds[] = { - { wl_display_get_fd(display), POLLIN }, + struct pollfd fds[] = + { + { wl_display_get_fd(_glfw.wl.display), POLLIN }, { _glfw.wl.timerfd, POLLIN }, { _glfw.wl.cursorTimerfd, POLLIN }, }; - ssize_t read_ret; - uint64_t repeats; - while (wl_display_prepare_read(display) != 0) - wl_display_dispatch_pending(display); + while (wl_display_prepare_read(_glfw.wl.display) != 0) + wl_display_dispatch_pending(_glfw.wl.display); - // If an error different from EAGAIN happens, we have likely been - // disconnected from the Wayland session, try to handle that the best we - // can. - if (wl_display_flush(display) < 0 && errno != EAGAIN) + // If an error other than EAGAIN happens, we have likely been disconnected + // from the Wayland session; try to handle that the best we can. + if (wl_display_flush(_glfw.wl.display) < 0 && errno != EAGAIN) { _GLFWwindow* window = _glfw.windowListHead; while (window) @@ -731,7 +728,8 @@ static void handleEvents(int timeout) _glfwInputWindowCloseRequest(window); window = window->next; } - wl_display_cancel_read(display); + + wl_display_cancel_read(_glfw.wl.display); return; } @@ -739,41 +737,42 @@ static void handleEvents(int timeout) { if (fds[0].revents & POLLIN) { - wl_display_read_events(display); - wl_display_dispatch_pending(display); + wl_display_read_events(_glfw.wl.display); + wl_display_dispatch_pending(_glfw.wl.display); } else - { - wl_display_cancel_read(display); - } + wl_display_cancel_read(_glfw.wl.display); if (fds[1].revents & POLLIN) { - read_ret = read(_glfw.wl.timerfd, &repeats, sizeof(repeats)); - if (read_ret == 8 && _glfw.wl.keyboardFocus) + uint64_t repeats; + + if (read(_glfw.wl.timerfd, &repeats, sizeof(repeats)) == 8) { - for (uint64_t i = 0; i < repeats; ++i) + if (_glfw.wl.keyboardFocus) { - _glfwInputKey(_glfw.wl.keyboardFocus, - _glfw.wl.keyboardLastKey, - _glfw.wl.keyboardLastScancode, - GLFW_REPEAT, - _glfw.wl.xkb.modifiers); + for (uint64_t i = 0; i < repeats; i++) + { + _glfwInputKey(_glfw.wl.keyboardFocus, + _glfw.wl.keyboardLastKey, + _glfw.wl.keyboardLastScancode, + GLFW_REPEAT, + _glfw.wl.xkb.modifiers); + } } } } if (fds[2].revents & POLLIN) { - read_ret = read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)); - if (read_ret == 8) + uint64_t repeats; + + if (read(_glfw.wl.cursorTimerfd, &repeats, sizeof(repeats)) == 8) incrementCursorImage(_glfw.wl.pointerFocus); } } else - { - wl_display_cancel_read(display); - } + wl_display_cancel_read(_glfw.wl.display); } ////////////////////////////////////////////////////////////////////////// From 850893a39f1e58ba5d6ff891ee18ca39037f921a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Mon, 27 Dec 2021 00:52:24 +0100 Subject: [PATCH 28/51] Wayland: Control key repeat via timerfd state The key repeat logic is now controlled only via the key repeat timerfd. --- src/wl_init.c | 6 +++--- src/wl_window.c | 15 ++++++--------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/src/wl_init.c b/src/wl_init.c index d26e5f6c..9ccd3530 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -504,12 +504,12 @@ static void keyboardHandleLeave(void* data, if (!window) return; + struct itimerspec timer = {}; + timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL); + _glfw.wl.serial = serial; _glfw.wl.keyboardFocus = NULL; _glfwInputWindowFocus(window, GLFW_FALSE); - - struct itimerspec timer = {}; - timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL); } static int toGLFWKeyCode(uint32_t key) diff --git a/src/wl_window.c b/src/wl_window.c index d51c9309..f2e268db 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -749,16 +749,13 @@ static void handleEvents(int timeout) if (read(_glfw.wl.timerfd, &repeats, sizeof(repeats)) == 8) { - if (_glfw.wl.keyboardFocus) + for (uint64_t i = 0; i < repeats; i++) { - for (uint64_t i = 0; i < repeats; i++) - { - _glfwInputKey(_glfw.wl.keyboardFocus, - _glfw.wl.keyboardLastKey, - _glfw.wl.keyboardLastScancode, - GLFW_REPEAT, - _glfw.wl.xkb.modifiers); - } + _glfwInputKey(_glfw.wl.keyboardFocus, + _glfw.wl.keyboardLastKey, + _glfw.wl.keyboardLastScancode, + GLFW_REPEAT, + _glfw.wl.xkb.modifiers); } } } From 3f5dfeaf295f69af006458f589e45c991d460fde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Sun, 26 Dec 2021 22:51:20 +0100 Subject: [PATCH 29/51] Wayland: Fix repeated key not released on defocus Platform code should not generate key events with GLFW_REPEAT. GLFW_PRESS is translated into GLFW_REPEAT by shared code based on the key state cache. This confused the automatic key release logic into not generating an event with GLFW_RELEASE for a key being repeated when the window lost input focus. --- README.md | 1 + src/wl_window.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9641fdf2..393a383d 100644 --- a/README.md +++ b/README.md @@ -283,6 +283,7 @@ information on what to include when reporting a bug. - [Wayland] Bugfix: Activating a window would emit two input focus events - [Wayland] Bugfix: Disable key repeat mechanism when window loses input focus - [Wayland] Bugfix: Window hiding and showing did not work (#1492,#1731) + - [Wayland] Bugfix: A key being repeated was not released when window lost focus - [POSIX] Removed use of deprecated function `gettimeofday` - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled - [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072) diff --git a/src/wl_window.c b/src/wl_window.c index f2e268db..26200363 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -754,7 +754,7 @@ static void handleEvents(int timeout) _glfwInputKey(_glfw.wl.keyboardFocus, _glfw.wl.keyboardLastKey, _glfw.wl.keyboardLastScancode, - GLFW_REPEAT, + GLFW_PRESS, _glfw.wl.xkb.modifiers); } } From a3d1633e1d48c2283da139116d70d5223642a804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Mon, 27 Dec 2021 18:10:52 +0100 Subject: [PATCH 30/51] Wayland: Move surface creation function This needs to be after createXdgSurface, which it will soon be calling. --- src/wl_window.c | 58 ++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index 26200363..e1fd96cb 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -432,35 +432,6 @@ static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable) } } -static GLFWbool createSurface(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig) -{ - window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor); - if (!window->wl.surface) - return GLFW_FALSE; - - wl_surface_add_listener(window->wl.surface, - &surfaceListener, - window); - - wl_surface_set_user_data(window->wl.surface, window); - - window->wl.native = wl_egl_window_create(window->wl.surface, - wndconfig->width, - wndconfig->height); - if (!window->wl.native) - return GLFW_FALSE; - - window->wl.width = wndconfig->width; - window->wl.height = wndconfig->height; - window->wl.scale = 1; - - if (!window->wl.transparent) - setOpaqueRegion(window); - - return GLFW_TRUE; -} - static void setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor, int refreshRate) { @@ -644,6 +615,35 @@ static GLFWbool createXdgSurface(_GLFWwindow* window) return GLFW_TRUE; } +static GLFWbool createSurface(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig) +{ + window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor); + if (!window->wl.surface) + return GLFW_FALSE; + + wl_surface_add_listener(window->wl.surface, + &surfaceListener, + window); + + wl_surface_set_user_data(window->wl.surface, window); + + window->wl.native = wl_egl_window_create(window->wl.surface, + wndconfig->width, + wndconfig->height); + if (!window->wl.native) + return GLFW_FALSE; + + window->wl.width = wndconfig->width; + window->wl.height = wndconfig->height; + window->wl.scale = 1; + + if (!window->wl.transparent) + setOpaqueRegion(window); + + return GLFW_TRUE; +} + static void setCursorImage(_GLFWwindow* window, _GLFWcursorWayland* cursorWayland) { From 7bede13b1dacb2ccf4d9492d0ec6bc0f7879222e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Mon, 27 Dec 2021 18:13:51 +0100 Subject: [PATCH 31/51] Wayland: Gather framebuffer transparency logic --- src/wl_window.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index e1fd96cb..28fdcb3d 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -616,7 +616,8 @@ static GLFWbool createXdgSurface(_GLFWwindow* window) } static GLFWbool createSurface(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig) + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig) { window->wl.surface = wl_compositor_create_surface(_glfw.wl.compositor); if (!window->wl.surface) @@ -638,6 +639,7 @@ static GLFWbool createSurface(_GLFWwindow* window, window->wl.height = wndconfig->height; window->wl.scale = 1; + window->wl.transparent = fbconfig->transparent; if (!window->wl.transparent) setOpaqueRegion(window); @@ -781,9 +783,7 @@ int _glfwCreateWindowWayland(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig) { - window->wl.transparent = fbconfig->transparent; - - if (!createSurface(window, wndconfig)) + if (!createSurface(window, wndconfig, fbconfig)) return GLFW_FALSE; if (ctxconfig->client != GLFW_NO_API) From c1ecd4673eae76d65a8a5e4222c46e20693f4e9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Mon, 27 Dec 2021 18:16:37 +0100 Subject: [PATCH 32/51] Wayland: Move window title cloning to creation --- src/wl_window.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index 28fdcb3d..2cfdee47 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -638,6 +638,7 @@ static GLFWbool createSurface(_GLFWwindow* window, window->wl.width = wndconfig->width; window->wl.height = wndconfig->height; window->wl.scale = 1; + window->wl.title = _glfw_strdup(wndconfig->title); window->wl.transparent = fbconfig->transparent; if (!window->wl.transparent) @@ -805,9 +806,6 @@ int _glfwCreateWindowWayland(_GLFWwindow* window, } } - if (wndconfig->title) - window->wl.title = _glfw_strdup(wndconfig->title); - window->wl.currentCursor = NULL; window->wl.monitors = _glfw_calloc(1, sizeof(_GLFWmonitor*)); From 216ea3d735e44691a5d06ee5654cd1ca14f685f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Mon, 27 Dec 2021 18:20:30 +0100 Subject: [PATCH 33/51] Wayland: Remove superfluous initialize to NULL The whole window struct has already been cleared to zero. --- src/wl_window.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index 2cfdee47..dfee3f34 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -806,8 +806,6 @@ int _glfwCreateWindowWayland(_GLFWwindow* window, } } - window->wl.currentCursor = NULL; - window->wl.monitors = _glfw_calloc(1, sizeof(_GLFWmonitor*)); window->wl.monitorsCount = 0; window->wl.monitorsSize = 1; From 12c2ccd609442f835e8f68b27bd903ab716f2531 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Mon, 27 Dec 2021 18:22:15 +0100 Subject: [PATCH 34/51] Wayland: Remove window monitor array pre-alloc The array will be allocated by surfaceHandleEnter when needed. --- src/wl_window.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index dfee3f34..6ad95f31 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -806,10 +806,6 @@ int _glfwCreateWindowWayland(_GLFWwindow* window, } } - window->wl.monitors = _glfw_calloc(1, sizeof(_GLFWmonitor*)); - window->wl.monitorsCount = 0; - window->wl.monitorsSize = 1; - return GLFW_TRUE; } From c05acf6246eefb08533dc3955db7eac9d2d1c0ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Tue, 28 Dec 2021 01:20:19 +0100 Subject: [PATCH 35/51] Wayland: Fix window not visible after initial swap A window created with GLFW_VISIBLE set was not made visible by the initial buffer swap during context attribute refresh. Regression introduced by @elmindreda in 094aa6d3c721397825cb1095c156353463ecafb5. --- src/wl_window.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/wl_window.c b/src/wl_window.c index 6ad95f31..b01d01f0 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -644,6 +644,14 @@ static GLFWbool createSurface(_GLFWwindow* window, if (!window->wl.transparent) setOpaqueRegion(window); + if (wndconfig->visible) + { + if (!createXdgSurface(window)) + return GLFW_FALSE; + + window->wl.visible = GLFW_TRUE; + } + return GLFW_TRUE; } From 25c521cbe5acd58641740db5063d33fb51eeb882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Tue, 28 Dec 2021 01:39:06 +0100 Subject: [PATCH 36/51] Wayland: Fix missing damage event on window show By definition a hidden window on Wayland does not have valid framebuffer contents. This adds a window damage (refresh) event when a window is shown, to request an initial frame for the now visible window. --- README.md | 1 + src/wl_window.c | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 393a383d..f2769580 100644 --- a/README.md +++ b/README.md @@ -284,6 +284,7 @@ information on what to include when reporting a bug. - [Wayland] Bugfix: Disable key repeat mechanism when window loses input focus - [Wayland] Bugfix: Window hiding and showing did not work (#1492,#1731) - [Wayland] Bugfix: A key being repeated was not released when window lost focus + - [Wayland] Bugfix: Showing a hidden window did not emit a window refresh event - [POSIX] Removed use of deprecated function `gettimeofday` - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled - [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072) diff --git a/src/wl_window.c b/src/wl_window.c index b01d01f0..a3190592 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1006,6 +1006,7 @@ void _glfwShowWindowWayland(_GLFWwindow* window) createXdgSurface(window); window->wl.visible = GLFW_TRUE; + _glfwInputWindowDamage(window); } } From 8aaea57421cd4e37b439fbce7482a5f351c0c31f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Tue, 28 Dec 2021 04:01:32 +0100 Subject: [PATCH 37/51] Fix gamma test not checking for NULL return value --- tests/gamma.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/gamma.c b/tests/gamma.c index 734955cd..d1f6dc27 100644 --- a/tests/gamma.c +++ b/tests/gamma.c @@ -113,6 +113,12 @@ int main(int argc, char** argv) { const GLFWgammaramp* ramp = glfwGetGammaRamp(monitor); + if (!ramp) + { + glfwTerminate(); + exit(EXIT_FAILURE); + } + const size_t array_size = ramp->size * sizeof(short); orig_ramp.size = ramp->size; orig_ramp.red = malloc(array_size); From 715b874db341d7f696a8244e4f3d5d14d07894bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Tue, 28 Dec 2021 15:33:58 +0100 Subject: [PATCH 38/51] Wayland: Fix GLFW_VISIBLE affecting full screen Full screen window creation was not ignoring the GLFW_VISIBLE hint. --- README.md | 1 + src/wl_window.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f2769580..abe5ed29 100644 --- a/README.md +++ b/README.md @@ -285,6 +285,7 @@ information on what to include when reporting a bug. - [Wayland] Bugfix: Window hiding and showing did not work (#1492,#1731) - [Wayland] Bugfix: A key being repeated was not released when window lost focus - [Wayland] Bugfix: Showing a hidden window did not emit a window refresh event + - [Wayland] Bugfix: Full screen window creation did not ignore `GLFW_VISIBLE` - [POSIX] Removed use of deprecated function `gettimeofday` - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled - [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072) diff --git a/src/wl_window.c b/src/wl_window.c index a3190592..eab108ee 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -644,7 +644,7 @@ static GLFWbool createSurface(_GLFWwindow* window, if (!window->wl.transparent) setOpaqueRegion(window); - if (wndconfig->visible) + if (window->monitor || wndconfig->visible) { if (!createXdgSurface(window)) return GLFW_FALSE; From 37b7540db9d850e9318fd1948dfb714f75306d50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 30 Dec 2021 02:59:15 +0100 Subject: [PATCH 39/51] Wayland: Fix keys reported as wrong or unknown key --- README.md | 1 + src/wl_init.c | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index abe5ed29..ae36e304 100644 --- a/README.md +++ b/README.md @@ -286,6 +286,7 @@ information on what to include when reporting a bug. - [Wayland] Bugfix: A key being repeated was not released when window lost focus - [Wayland] Bugfix: Showing a hidden window did not emit a window refresh event - [Wayland] Bugfix: Full screen window creation did not ignore `GLFW_VISIBLE` + - [Wayland] Bugfix: Some keys were reported as wrong key or `GLFW_KEY_UNKNOWN` - [POSIX] Removed use of deprecated function `gettimeofday` - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled - [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072) diff --git a/src/wl_init.c b/src/wl_init.c index 9ccd3530..3d28bddc 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -972,7 +972,7 @@ static void createKeyTables(void) _glfw.wl.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT; _glfw.wl.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER; _glfw.wl.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER; - _glfw.wl.keycodes[KEY_MENU] = GLFW_KEY_MENU; + _glfw.wl.keycodes[KEY_COMPOSE] = GLFW_KEY_MENU; _glfw.wl.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK; _glfw.wl.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK; _glfw.wl.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN; @@ -1015,7 +1015,7 @@ static void createKeyTables(void) _glfw.wl.keycodes[KEY_F23] = GLFW_KEY_F23; _glfw.wl.keycodes[KEY_F24] = GLFW_KEY_F24; _glfw.wl.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE; - _glfw.wl.keycodes[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY; + _glfw.wl.keycodes[KEY_KPASTERISK] = GLFW_KEY_KP_MULTIPLY; _glfw.wl.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT; _glfw.wl.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD; _glfw.wl.keycodes[KEY_KP0] = GLFW_KEY_KP_0; @@ -1028,9 +1028,10 @@ static void createKeyTables(void) _glfw.wl.keycodes[KEY_KP7] = GLFW_KEY_KP_7; _glfw.wl.keycodes[KEY_KP8] = GLFW_KEY_KP_8; _glfw.wl.keycodes[KEY_KP9] = GLFW_KEY_KP_9; - _glfw.wl.keycodes[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL; + _glfw.wl.keycodes[KEY_KPDOT] = GLFW_KEY_KP_DECIMAL; _glfw.wl.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL; _glfw.wl.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER; + _glfw.wl.keycodes[KEY_102ND] = GLFW_KEY_WORLD_2; for (int scancode = 0; scancode < 256; scancode++) { From cb22c5411938c14a3ddef6f0fb4f338a6b4b99a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 30 Dec 2021 18:22:16 +0100 Subject: [PATCH 40/51] Move UTF-8 encoding to shared code This will be used by the Wayland code too. --- src/init.c | 31 +++++++++++++++++++++++++++++++ src/internal.h | 2 ++ src/x11_window.c | 35 ++--------------------------------- 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/src/init.c b/src/init.c index b5c5da9c..1d4e7804 100644 --- a/src/init.c +++ b/src/init.c @@ -140,6 +140,37 @@ static void terminate(void) ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// +// Encode a Unicode code point to a UTF-8 stream +// Based on cutef8 by Jeff Bezanson (Public Domain) +// +size_t _glfwEncodeUTF8(char* s, unsigned int ch) +{ + size_t count = 0; + + if (ch < 0x80) + s[count++] = (char) ch; + else if (ch < 0x800) + { + s[count++] = (ch >> 6) | 0xc0; + s[count++] = (ch & 0x3f) | 0x80; + } + else if (ch < 0x10000) + { + s[count++] = (ch >> 12) | 0xe0; + s[count++] = ((ch >> 6) & 0x3f) | 0x80; + s[count++] = (ch & 0x3f) | 0x80; + } + else if (ch < 0x110000) + { + s[count++] = (ch >> 18) | 0xf0; + s[count++] = ((ch >> 12) & 0x3f) | 0x80; + s[count++] = ((ch >> 6) & 0x3f) | 0x80; + s[count++] = (ch & 0x3f) | 0x80; + } + + return count; +} + char* _glfw_strdup(const char* source) { const size_t length = strlen(source); diff --git a/src/internal.h b/src/internal.h index 2a8c8d6d..b28d41ab 100644 --- a/src/internal.h +++ b/src/internal.h @@ -995,6 +995,8 @@ GLFWbool _glfwInitVulkan(int mode); void _glfwTerminateVulkan(void); const char* _glfwGetVulkanResultString(VkResult result); +size_t _glfwEncodeUTF8(char* s, unsigned int ch); + char* _glfw_strdup(const char* source); float _glfw_fminf(float a, float b); float _glfw_fmaxf(float a, float b); diff --git a/src/x11_window.c b/src/x11_window.c index a5255215..96514c18 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -429,37 +429,6 @@ static char** parseUriList(char* text, int* count) return paths; } -// Encode a Unicode code point to a UTF-8 stream -// Based on cutef8 by Jeff Bezanson (Public Domain) -// -static size_t encodeUTF8(char* s, unsigned int ch) -{ - size_t count = 0; - - if (ch < 0x80) - s[count++] = (char) ch; - else if (ch < 0x800) - { - s[count++] = (ch >> 6) | 0xc0; - s[count++] = (ch & 0x3f) | 0x80; - } - else if (ch < 0x10000) - { - s[count++] = (ch >> 12) | 0xe0; - s[count++] = ((ch >> 6) & 0x3f) | 0x80; - s[count++] = (ch & 0x3f) | 0x80; - } - else if (ch < 0x110000) - { - s[count++] = (ch >> 18) | 0xf0; - s[count++] = ((ch >> 12) & 0x3f) | 0x80; - s[count++] = ((ch >> 6) & 0x3f) | 0x80; - s[count++] = (ch & 0x3f) | 0x80; - } - - return count; -} - // Decode a Unicode code point from a UTF-8 stream // Based on cutef8 by Jeff Bezanson (Public Domain) // @@ -497,7 +466,7 @@ static char* convertLatin1toUTF8(const char* source) char* tp = target; for (sp = source; *sp; sp++) - tp += encodeUTF8(tp, *sp); + tp += _glfwEncodeUTF8(tp, *sp); return target; } @@ -2903,7 +2872,7 @@ const char* _glfwGetScancodeNameX11(int scancode) if (ch == -1) return NULL; - const size_t count = encodeUTF8(_glfw.x11.keynames[key], (unsigned int) ch); + const size_t count = _glfwEncodeUTF8(_glfw.x11.keynames[key], (unsigned int) ch); if (count == 0) return NULL; From 17a9e34fbc179373dc9bc370164fa4690870b295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 29 Dec 2021 23:45:06 +0100 Subject: [PATCH 41/51] Wayland: Implement key name support --- README.md | 1 + src/wl_init.c | 4 ++++ src/wl_platform.h | 7 ++++++ src/wl_window.c | 55 +++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 63 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ae36e304..06108a86 100644 --- a/README.md +++ b/README.md @@ -266,6 +266,7 @@ information on what to include when reporting a bug. undefined behavior (#1986) - [X11] Bugfix: Dynamic loading on OpenBSD failed due to soname differences - [Wayland] Added dynamic loading of all Wayland libraries + - [Wayland] Added support for key names via xkbcommon - [Wayland] Removed support for `wl_shell` (#1443) - [Wayland] Bugfix: The `GLFW_HAND_CURSOR` shape used the wrong image (#1432) - [Wayland] Bugfix: `CLOCK_MONOTONIC` was not correctly enabled diff --git a/src/wl_init.c b/src/wl_init.c index 3d28bddc..bd365fdf 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -1290,6 +1290,8 @@ int _glfwInitWayland(void) _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index"); _glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats) _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats"); + _glfw.wl.xkb.keymap_key_get_syms_by_level = (PFN_xkb_keymap_key_get_syms_by_level) + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_keymap_key_get_syms_by_level"); _glfw.wl.xkb.state_new = (PFN_xkb_state_new) _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_new"); _glfw.wl.xkb.state_unref = (PFN_xkb_state_unref) @@ -1300,6 +1302,8 @@ int _glfwInitWayland(void) _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_update_mask"); _glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods) _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_serialize_mods"); + _glfw.wl.xkb.state_key_get_layout = (PFN_xkb_state_key_get_layout) + _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_key_get_layout"); #ifdef HAVE_XKBCOMMON_COMPOSE_H _glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale) diff --git a/src/wl_platform.h b/src/wl_platform.h index 1e36a794..e29f41b4 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -163,22 +163,26 @@ typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*); typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*); typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t); +typedef int (* PFN_xkb_keymap_key_get_syms_by_level)(struct xkb_keymap*,xkb_keycode_t,xkb_layout_index_t,xkb_level_index_t,const xkb_keysym_t**); typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*); typedef void (* PFN_xkb_state_unref)(struct xkb_state*); typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**); typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t); typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component); +typedef xkb_layout_index_t (* PFN_xkb_state_key_get_layout)(struct xkb_state*,xkb_keycode_t); #define xkb_context_new _glfw.wl.xkb.context_new #define xkb_context_unref _glfw.wl.xkb.context_unref #define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string #define xkb_keymap_unref _glfw.wl.xkb.keymap_unref #define xkb_keymap_mod_get_index _glfw.wl.xkb.keymap_mod_get_index #define xkb_keymap_key_repeats _glfw.wl.xkb.keymap_key_repeats +#define xkb_keymap_key_get_syms_by_level _glfw.wl.xkb.keymap_key_get_syms_by_level #define xkb_state_new _glfw.wl.xkb.state_new #define xkb_state_unref _glfw.wl.xkb.state_unref #define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms #define xkb_state_update_mask _glfw.wl.xkb.state_update_mask #define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods +#define xkb_state_key_get_layout _glfw.wl.xkb.state_key_get_layout #ifdef HAVE_XKBCOMMON_COMPOSE_H typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags); @@ -311,6 +315,7 @@ typedef struct _GLFWlibraryWayland int timerfd; short int keycodes[256]; short int scancodes[GLFW_KEY_LAST + 1]; + char keynames[GLFW_KEY_LAST + 1][5]; struct { void* handle; @@ -336,11 +341,13 @@ typedef struct _GLFWlibraryWayland PFN_xkb_keymap_unref keymap_unref; PFN_xkb_keymap_mod_get_index keymap_mod_get_index; PFN_xkb_keymap_key_repeats keymap_key_repeats; + PFN_xkb_keymap_key_get_syms_by_level keymap_key_get_syms_by_level; PFN_xkb_state_new state_new; PFN_xkb_state_unref state_unref; PFN_xkb_state_key_get_syms state_key_get_syms; PFN_xkb_state_update_mask state_update_mask; PFN_xkb_state_serialize_mods state_serialize_mods; + PFN_xkb_state_key_get_layout state_key_get_layout; #ifdef HAVE_XKBCOMMON_COMPOSE_H PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale; diff --git a/src/wl_window.c b/src/wl_window.c index eab108ee..1ed4b079 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1193,10 +1193,57 @@ void _glfwSetCursorModeWayland(_GLFWwindow* window, int mode) const char* _glfwGetScancodeNameWayland(int scancode) { - // TODO - _glfwInputError(GLFW_FEATURE_UNIMPLEMENTED, - "Wayland: Key names not yet implemented"); - return NULL; + if (scancode < 0 || scancode > 255 || + _glfw.wl.keycodes[scancode] == GLFW_KEY_UNKNOWN) + { + _glfwInputError(GLFW_INVALID_VALUE, + "Wayland: Invalid scancode %i", + scancode); + return NULL; + } + + const int key = _glfw.wl.keycodes[scancode]; + const xkb_keycode_t keycode = scancode + 8; + const xkb_layout_index_t layout = + xkb_state_key_get_layout(_glfw.wl.xkb.state, keycode); + if (layout == XKB_LAYOUT_INVALID) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to retrieve layout for key name"); + return NULL; + } + + const xkb_keysym_t* keysyms = NULL; + xkb_keymap_key_get_syms_by_level(_glfw.wl.xkb.keymap, + keycode, + layout, + 0, + &keysyms); + if (keysyms == NULL) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to retrieve keysym for key name"); + return NULL; + } + + const long codepoint = _glfwKeySym2Unicode(keysyms[0]); + if (codepoint == -1) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to retrieve codepoint for key name"); + return NULL; + } + + const size_t count = _glfwEncodeUTF8(_glfw.wl.keynames[key], (unsigned int) codepoint); + if (count == 0) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to encode codepoint for key name"); + return NULL; + } + + _glfw.wl.keynames[key][count] = '\0'; + return _glfw.wl.keynames[key]; } int _glfwGetKeyScancodeWayland(int key) From fe7be39793f993f9bf7480f2389bffad676199f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 30 Dec 2021 19:09:53 +0100 Subject: [PATCH 42/51] Clean up internal Unicode code point handling Call code points by their name and store them as uint32_t. --- src/init.c | 30 +++++++++++++++--------------- src/input.c | 2 +- src/internal.h | 4 ++-- src/win32_window.c | 4 ++-- src/wl_init.c | 9 ++++----- src/wl_window.c | 6 +++--- src/x11_window.c | 22 +++++++++++----------- src/xkb_unicode.c | 4 ++-- src/xkb_unicode.h | 4 +++- 9 files changed, 43 insertions(+), 42 deletions(-) diff --git a/src/init.c b/src/init.c index 1d4e7804..80f424a8 100644 --- a/src/init.c +++ b/src/init.c @@ -143,29 +143,29 @@ static void terminate(void) // Encode a Unicode code point to a UTF-8 stream // Based on cutef8 by Jeff Bezanson (Public Domain) // -size_t _glfwEncodeUTF8(char* s, unsigned int ch) +size_t _glfwEncodeUTF8(char* s, uint32_t codepoint) { size_t count = 0; - if (ch < 0x80) - s[count++] = (char) ch; - else if (ch < 0x800) + if (codepoint < 0x80) + s[count++] = (char) codepoint; + else if (codepoint < 0x800) { - s[count++] = (ch >> 6) | 0xc0; - s[count++] = (ch & 0x3f) | 0x80; + s[count++] = (codepoint >> 6) | 0xc0; + s[count++] = (codepoint & 0x3f) | 0x80; } - else if (ch < 0x10000) + else if (codepoint < 0x10000) { - s[count++] = (ch >> 12) | 0xe0; - s[count++] = ((ch >> 6) & 0x3f) | 0x80; - s[count++] = (ch & 0x3f) | 0x80; + s[count++] = (codepoint >> 12) | 0xe0; + s[count++] = ((codepoint >> 6) & 0x3f) | 0x80; + s[count++] = (codepoint & 0x3f) | 0x80; } - else if (ch < 0x110000) + else if (codepoint < 0x110000) { - s[count++] = (ch >> 18) | 0xf0; - s[count++] = ((ch >> 12) & 0x3f) | 0x80; - s[count++] = ((ch >> 6) & 0x3f) | 0x80; - s[count++] = (ch & 0x3f) | 0x80; + s[count++] = (codepoint >> 18) | 0xf0; + s[count++] = ((codepoint >> 12) & 0x3f) | 0x80; + s[count++] = ((codepoint >> 6) & 0x3f) | 0x80; + s[count++] = (codepoint & 0x3f) | 0x80; } return count; diff --git a/src/input.c b/src/input.c index 11716bd5..6a2c3e1d 100644 --- a/src/input.c +++ b/src/input.c @@ -295,7 +295,7 @@ void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int m // Notifies shared code of a Unicode codepoint input event // The 'plain' parameter determines whether to emit a regular character event // -void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain) +void _glfwInputChar(_GLFWwindow* window, uint32_t codepoint, int mods, GLFWbool plain) { if (codepoint < 32 || (codepoint > 126 && codepoint < 160)) return; diff --git a/src/internal.h b/src/internal.h index b28d41ab..f8548fa3 100644 --- a/src/internal.h +++ b/src/internal.h @@ -919,7 +919,7 @@ void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor); void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods); void _glfwInputChar(_GLFWwindow* window, - unsigned int codepoint, int mods, GLFWbool plain); + uint32_t codepoint, int mods, GLFWbool plain); void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset); void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods); void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos); @@ -995,7 +995,7 @@ GLFWbool _glfwInitVulkan(int mode); void _glfwTerminateVulkan(void); const char* _glfwGetVulkanResultString(VkResult result); -size_t _glfwEncodeUTF8(char* s, unsigned int ch); +size_t _glfwEncodeUTF8(char* s, uint32_t codepoint); char* _glfw_strdup(const char* source); float _glfw_fminf(float a, float b); diff --git a/src/win32_window.c b/src/win32_window.c index e03b8564..b3da6b2a 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -649,7 +649,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, window->win32.highSurrogate = (WCHAR) wParam; else { - unsigned int codepoint = 0; + uint32_t codepoint = 0; if (wParam >= 0xdc00 && wParam <= 0xdfff) { @@ -683,7 +683,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, return TRUE; } - _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GLFW_TRUE); + _glfwInputChar(window, (uint32_t) wParam, getKeyMods(), GLFW_TRUE); return 0; } diff --git a/src/wl_init.c b/src/wl_init.c index bd365fdf..e2bd2921 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -544,8 +544,7 @@ static xkb_keysym_t composeSymbol(xkb_keysym_t sym) static GLFWbool inputChar(_GLFWwindow* window, uint32_t key) { - uint32_t code, numSyms; - long cp; + uint32_t code, numSyms, codepoint; const xkb_keysym_t *syms; xkb_keysym_t sym; @@ -559,12 +558,12 @@ static GLFWbool inputChar(_GLFWwindow* window, uint32_t key) #else sym = syms[0]; #endif - cp = _glfwKeySym2Unicode(sym); - if (cp != -1) + codepoint = _glfwKeySym2Unicode(sym); + if (codepoint != GLFW_INVALID_CODEPOINT) { const int mods = _glfw.wl.xkb.modifiers; const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); - _glfwInputChar(window, cp, mods, plain); + _glfwInputChar(window, codepoint, mods, plain); } } diff --git a/src/wl_window.c b/src/wl_window.c index 1ed4b079..48ffb7c2 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1226,15 +1226,15 @@ const char* _glfwGetScancodeNameWayland(int scancode) return NULL; } - const long codepoint = _glfwKeySym2Unicode(keysyms[0]); - if (codepoint == -1) + const uint32_t codepoint = _glfwKeySym2Unicode(keysyms[0]); + if (codepoint == GLFW_INVALID_CODEPOINT) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to retrieve codepoint for key name"); return NULL; } - const size_t count = _glfwEncodeUTF8(_glfw.wl.keynames[key], (unsigned int) codepoint); + const size_t count = _glfwEncodeUTF8(_glfw.wl.keynames[key], codepoint); if (count == 0) { _glfwInputError(GLFW_PLATFORM_ERROR, diff --git a/src/x11_window.c b/src/x11_window.c index 96514c18..61e4fd6d 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -432,10 +432,10 @@ static char** parseUriList(char* text, int* count) // Decode a Unicode code point from a UTF-8 stream // Based on cutef8 by Jeff Bezanson (Public Domain) // -static unsigned int decodeUTF8(const char** s) +static uint32_t decodeUTF8(const char** s) { - unsigned int ch = 0, count = 0; - static const unsigned int offsets[] = + uint32_t codepoint = 0, count = 0; + static const uint32_t offsets[] = { 0x00000000u, 0x00003080u, 0x000e2080u, 0x03c82080u, 0xfa082080u, 0x82082080u @@ -443,13 +443,13 @@ static unsigned int decodeUTF8(const char** s) do { - ch = (ch << 6) + (unsigned char) **s; + codepoint = (codepoint << 6) + (unsigned char) **s; (*s)++; count++; } while ((**s & 0xc0) == 0x80); assert(count <= 6); - return ch - offsets[count - 1]; + return codepoint - offsets[count - 1]; } // Convert the specified Latin-1 string to UTF-8 @@ -1286,9 +1286,9 @@ static void processEvent(XEvent *event) _glfwInputKey(window, key, keycode, GLFW_PRESS, mods); - const long character = _glfwKeySym2Unicode(keysym); - if (character != -1) - _glfwInputChar(window, character, mods, plain); + const uint32_t codepoint = _glfwKeySym2Unicode(keysym); + if (codepoint != GLFW_INVALID_CODEPOINT) + _glfwInputChar(window, codepoint, mods, plain); } return; @@ -2868,11 +2868,11 @@ const char* _glfwGetScancodeNameX11(int scancode) if (keysym == NoSymbol) return NULL; - const long ch = _glfwKeySym2Unicode(keysym); - if (ch == -1) + const uint32_t codepoint = _glfwKeySym2Unicode(keysym); + if (codepoint == GLFW_INVALID_CODEPOINT) return NULL; - const size_t count = _glfwEncodeUTF8(_glfw.x11.keynames[key], (unsigned int) ch); + const size_t count = _glfwEncodeUTF8(_glfw.x11.keynames[key], codepoint); if (count == 0) return NULL; diff --git a/src/xkb_unicode.c b/src/xkb_unicode.c index 2772ea09..1b2482cd 100644 --- a/src/xkb_unicode.c +++ b/src/xkb_unicode.c @@ -907,7 +907,7 @@ static const struct codepair { // Convert XKB KeySym to Unicode // -long _glfwKeySym2Unicode(unsigned int keysym) +uint32_t _glfwKeySym2Unicode(unsigned int keysym) { int min = 0; int max = sizeof(keysymtab) / sizeof(struct codepair) - 1; @@ -937,6 +937,6 @@ long _glfwKeySym2Unicode(unsigned int keysym) } // No matching Unicode value found - return -1; + return GLFW_INVALID_CODEPOINT; } diff --git a/src/xkb_unicode.h b/src/xkb_unicode.h index 76d83ffd..b07408f6 100644 --- a/src/xkb_unicode.h +++ b/src/xkb_unicode.h @@ -24,5 +24,7 @@ // //======================================================================== -long _glfwKeySym2Unicode(unsigned int keysym); +#define GLFW_INVALID_CODEPOINT 0xffffffffu + +uint32_t _glfwKeySym2Unicode(unsigned int keysym); From b70259e52df8cf5b1773ae7f0b575a0d6107454e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 30 Dec 2021 19:49:06 +0100 Subject: [PATCH 43/51] Wayland: Clean up text input Adapt style and naming to match the rest of the project. --- src/wl_init.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/wl_init.c b/src/wl_init.c index e2bd2921..b1f98733 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -542,23 +542,19 @@ static xkb_keysym_t composeSymbol(xkb_keysym_t sym) } #endif -static GLFWbool inputChar(_GLFWwindow* window, uint32_t key) +static GLFWbool inputChar(_GLFWwindow* window, uint32_t scancode) { - uint32_t code, numSyms, codepoint; - const xkb_keysym_t *syms; - xkb_keysym_t sym; + const xkb_keysym_t* keysyms; + const xkb_keycode_t keycode = scancode + 8; - code = key + 8; - numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms); - - if (numSyms == 1) + if (xkb_state_key_get_syms(_glfw.wl.xkb.state, keycode, &keysyms) == 1) { #ifdef HAVE_XKBCOMMON_COMPOSE_H - sym = composeSymbol(syms[0]); + const xkb_keysym_t keysym = composeSymbol(keysyms[0]); #else - sym = syms[0]; + const xkb_keysym_t keysym = keysyms[0]; #endif - codepoint = _glfwKeySym2Unicode(sym); + const uint32_t codepoint = _glfwKeySym2Unicode(keysym); if (codepoint != GLFW_INVALID_CODEPOINT) { const int mods = _glfw.wl.xkb.modifiers; @@ -567,7 +563,7 @@ static GLFWbool inputChar(_GLFWwindow* window, uint32_t key) } } - return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, code); + return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, keycode); } static void keyboardHandleKey(void* data, From 293d19a1537e25d6a47c0e8fb080f94061f8d131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 30 Dec 2021 20:02:45 +0100 Subject: [PATCH 44/51] Wayland: Require xkbcommon 0.5.0 or greater The Wayland backend now requires xkbcommon-compose, which was added in version 0.5.0. xkbcommon 0.5.0 was released in 2014. This removes the non-composing fallback path for text input. --- docs/compat.dox | 5 ++--- src/CMakeLists.txt | 6 +----- src/wl_init.c | 16 ---------------- src/wl_platform.h | 8 -------- 4 files changed, 3 insertions(+), 32 deletions(-) diff --git a/docs/compat.dox b/docs/compat.dox index 5b264b3f..989c4c19 100644 --- a/docs/compat.dox +++ b/docs/compat.dox @@ -104,9 +104,8 @@ integration by libwayland-egl, and keyboard handling by from wayland-protocols to provide additional features if the compositor supports them. -GLFW uses xkbcommon 0.5.0 to provide compose key support. When it has been -built against an older xkbcommon, the compose key will be disabled even if it -has been configured in the compositor. +GLFW uses xkbcommon 0.5.0 to provide key and text input support. Earlier +versions are not supported. GLFW uses the [xdg-shell protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/xdg-shell/xdg-shell.xml) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 16cb1749..a07ca931 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -65,10 +65,6 @@ endif() if (GLFW_BUILD_WAYLAND) include(CheckIncludeFiles) include(CheckFunctionExists) - check_include_files(xkbcommon/xkbcommon-compose.h HAVE_XKBCOMMON_COMPOSE_H) - if (HAVE_XKBCOMMON_COMPOSE_H) - target_compile_definitions(glfw PRIVATE HAVE_XKBCOMMON_COMPOSE_H) - endif() check_function_exists(memfd_create HAVE_MEMFD_CREATE) if (HAVE_MEMFD_CREATE) target_compile_definitions(glfw PRIVATE HAVE_MEMFD_CREATE) @@ -173,7 +169,7 @@ if (GLFW_BUILD_WAYLAND) wayland-client>=0.2.7 wayland-cursor>=0.2.7 wayland-egl>=0.2.7 - xkbcommon) + xkbcommon>=0.5.0) target_include_directories(glfw PRIVATE ${Wayland_INCLUDE_DIRS}) diff --git a/src/wl_init.c b/src/wl_init.c index b1f98733..d9a70287 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -377,11 +377,8 @@ static void keyboardHandleKeymap(void* data, { struct xkb_keymap* keymap; struct xkb_state* state; - -#ifdef HAVE_XKBCOMMON_COMPOSE_H struct xkb_compose_table* composeTable; struct xkb_compose_state* composeState; -#endif char* mapStr; const char* locale; @@ -430,7 +427,6 @@ static void keyboardHandleKeymap(void* data, if (!locale) locale = "C"; -#ifdef HAVE_XKBCOMMON_COMPOSE_H composeTable = xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale, XKB_COMPOSE_COMPILE_NO_FLAGS); @@ -450,7 +446,6 @@ static void keyboardHandleKeymap(void* data, _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to create XKB compose table"); } -#endif xkb_keymap_unref(_glfw.wl.xkb.keymap); xkb_state_unref(_glfw.wl.xkb.state); @@ -520,7 +515,6 @@ static int toGLFWKeyCode(uint32_t key) return GLFW_KEY_UNKNOWN; } -#ifdef HAVE_XKBCOMMON_COMPOSE_H static xkb_keysym_t composeSymbol(xkb_keysym_t sym) { if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState) @@ -540,7 +534,6 @@ static xkb_keysym_t composeSymbol(xkb_keysym_t sym) return sym; } } -#endif static GLFWbool inputChar(_GLFWwindow* window, uint32_t scancode) { @@ -549,11 +542,7 @@ static GLFWbool inputChar(_GLFWwindow* window, uint32_t scancode) if (xkb_state_key_get_syms(_glfw.wl.xkb.state, keycode, &keysyms) == 1) { -#ifdef HAVE_XKBCOMMON_COMPOSE_H const xkb_keysym_t keysym = composeSymbol(keysyms[0]); -#else - const xkb_keysym_t keysym = keysyms[0]; -#endif const uint32_t codepoint = _glfwKeySym2Unicode(keysym); if (codepoint != GLFW_INVALID_CODEPOINT) { @@ -1299,8 +1288,6 @@ int _glfwInitWayland(void) _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_serialize_mods"); _glfw.wl.xkb.state_key_get_layout = (PFN_xkb_state_key_get_layout) _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_state_key_get_layout"); - -#ifdef HAVE_XKBCOMMON_COMPOSE_H _glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale) _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale"); _glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref) @@ -1315,7 +1302,6 @@ int _glfwInitWayland(void) _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_get_status"); _glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym) _glfwPlatformGetModuleSymbol(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym"); -#endif _glfw.wl.registry = wl_display_get_registry(_glfw.wl.display); wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL); @@ -1403,10 +1389,8 @@ void _glfwTerminateWayland(void) _glfw.wl.egl.handle = NULL; } -#ifdef HAVE_XKBCOMMON_COMPOSE_H if (_glfw.wl.xkb.composeState) xkb_compose_state_unref(_glfw.wl.xkb.composeState); -#endif if (_glfw.wl.xkb.keymap) xkb_keymap_unref(_glfw.wl.xkb.keymap); if (_glfw.wl.xkb.state) diff --git a/src/wl_platform.h b/src/wl_platform.h index e29f41b4..a26bd23e 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -26,9 +26,7 @@ #include #include -#ifdef HAVE_XKBCOMMON_COMPOSE_H #include -#endif typedef VkFlags VkWaylandSurfaceCreateFlagsKHR; @@ -184,7 +182,6 @@ typedef xkb_layout_index_t (* PFN_xkb_state_key_get_layout)(struct xkb_state*,xk #define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods #define xkb_state_key_get_layout _glfw.wl.xkb.state_key_get_layout -#ifdef HAVE_XKBCOMMON_COMPOSE_H typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags); typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*); typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags); @@ -199,7 +196,6 @@ typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_st #define xkb_compose_state_feed _glfw.wl.xkb.compose_state_feed #define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status #define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym -#endif #define _GLFW_DECORATION_WIDTH 4 #define _GLFW_DECORATION_TOP 24 @@ -323,9 +319,7 @@ typedef struct _GLFWlibraryWayland struct xkb_keymap* keymap; struct xkb_state* state; -#ifdef HAVE_XKBCOMMON_COMPOSE_H struct xkb_compose_state* composeState; -#endif xkb_mod_mask_t controlMask; xkb_mod_mask_t altMask; @@ -349,7 +343,6 @@ typedef struct _GLFWlibraryWayland PFN_xkb_state_serialize_mods state_serialize_mods; PFN_xkb_state_key_get_layout state_key_get_layout; -#ifdef HAVE_XKBCOMMON_COMPOSE_H PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale; PFN_xkb_compose_table_unref compose_table_unref; PFN_xkb_compose_state_new compose_state_new; @@ -357,7 +350,6 @@ typedef struct _GLFWlibraryWayland PFN_xkb_compose_state_feed compose_state_feed; PFN_xkb_compose_state_get_status compose_state_get_status; PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym; -#endif } xkb; _GLFWwindow* pointerFocus; From bf995870052d5076ce80c4728eb6fd4054dd9742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 30 Dec 2021 21:06:22 +0100 Subject: [PATCH 45/51] Wayland: Clean up key event handler Adapt style and naming to match the rest of the project. --- src/wl_init.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/wl_init.c b/src/wl_init.c index d9a70287..c57a7e73 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -559,42 +559,40 @@ static void keyboardHandleKey(void* data, struct wl_keyboard* keyboard, uint32_t serial, uint32_t time, - uint32_t key, + uint32_t scancode, uint32_t state) { - int keyCode; - int action; _GLFWwindow* window = _glfw.wl.keyboardFocus; - GLFWbool shouldRepeat; - struct itimerspec timer = {}; - if (!window) return; - keyCode = toGLFWKeyCode(key); - action = state == WL_KEYBOARD_KEY_STATE_PRESSED - ? GLFW_PRESS : GLFW_RELEASE; + const int key = toGLFWKeyCode(scancode); + const int action = + state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE; _glfw.wl.serial = serial; - _glfwInputKey(window, keyCode, key, action, - _glfw.wl.xkb.modifiers); + _glfwInputKey(window, key, scancode, action, _glfw.wl.xkb.modifiers); + + struct itimerspec timer = {}; if (action == GLFW_PRESS) { - shouldRepeat = inputChar(window, key); + const GLFWbool shouldRepeat = inputChar(window, scancode); if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0) { - _glfw.wl.keyboardLastKey = keyCode; - _glfw.wl.keyboardLastScancode = key; + _glfw.wl.keyboardLastKey = key; + _glfw.wl.keyboardLastScancode = scancode; if (_glfw.wl.keyboardRepeatRate > 1) timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyboardRepeatRate; else timer.it_interval.tv_sec = 1; + timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000; timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000; } } + timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL); } From 1a7da42e6ebaa4e8eeffb693c32c8d36d54ddf6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 30 Dec 2021 21:09:23 +0100 Subject: [PATCH 46/51] Wayland: Fix text input not following key repeat The manual key repeat implementation did not call text input. --- README.md | 1 + src/wl_init.c | 4 ++-- src/wl_platform.h | 1 + src/wl_window.c | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 06108a86..4a3fb85c 100644 --- a/README.md +++ b/README.md @@ -288,6 +288,7 @@ information on what to include when reporting a bug. - [Wayland] Bugfix: Showing a hidden window did not emit a window refresh event - [Wayland] Bugfix: Full screen window creation did not ignore `GLFW_VISIBLE` - [Wayland] Bugfix: Some keys were reported as wrong key or `GLFW_KEY_UNKNOWN` + - [Wayland] Bugfix: Text input did not repeat along with key repeat - [POSIX] Removed use of deprecated function `gettimeofday` - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled - [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072) diff --git a/src/wl_init.c b/src/wl_init.c index c57a7e73..83cd7aca 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -535,7 +535,7 @@ static xkb_keysym_t composeSymbol(xkb_keysym_t sym) } } -static GLFWbool inputChar(_GLFWwindow* window, uint32_t scancode) +GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode) { const xkb_keysym_t* keysyms; const xkb_keycode_t keycode = scancode + 8; @@ -577,7 +577,7 @@ static void keyboardHandleKey(void* data, if (action == GLFW_PRESS) { - const GLFWbool shouldRepeat = inputChar(window, scancode); + const GLFWbool shouldRepeat = _glfwInputTextWayland(window, scancode); if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0) { diff --git a/src/wl_platform.h b/src/wl_platform.h index a26bd23e..7565411b 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -495,4 +495,5 @@ GLFWbool _glfwGetGammaRampWayland(_GLFWmonitor* monitor, GLFWgammaramp* ramp); void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp); void _glfwAddOutputWayland(uint32_t name, uint32_t version); +GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode); diff --git a/src/wl_window.c b/src/wl_window.c index 48ffb7c2..b2aa1800 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -767,6 +767,8 @@ static void handleEvents(int timeout) _glfw.wl.keyboardLastScancode, GLFW_PRESS, _glfw.wl.xkb.modifiers); + _glfwInputTextWayland(_glfw.wl.keyboardFocus, + _glfw.wl.keyboardLastScancode); } } } From 0ce611958ee6fe9ddbd799986711759c9156566a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Fri, 31 Dec 2021 00:19:08 +0100 Subject: [PATCH 47/51] Wayland: Clean up key translation Adapt style and naming to match the rest of the project. --- src/wl_init.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/wl_init.c b/src/wl_init.c index 83cd7aca..2f138578 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -507,10 +507,10 @@ static void keyboardHandleLeave(void* data, _glfwInputWindowFocus(window, GLFW_FALSE); } -static int toGLFWKeyCode(uint32_t key) +static int translateKey(uint32_t scancode) { - if (key < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0])) - return _glfw.wl.keycodes[key]; + if (scancode < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0])) + return _glfw.wl.keycodes[scancode]; return GLFW_KEY_UNKNOWN; } @@ -566,7 +566,7 @@ static void keyboardHandleKey(void* data, if (!window) return; - const int key = toGLFWKeyCode(scancode); + const int key = translateKey(scancode); const int action = state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE; From df8d7bc892937a8b0f7c604c92a9f64f383cf48c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Fri, 31 Dec 2021 00:19:58 +0100 Subject: [PATCH 48/51] Wayland: Clean up modifier key event handler Adapt style and naming to match the rest of the project. --- src/wl_init.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/wl_init.c b/src/wl_init.c index 2f138578..e7756385 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -604,9 +604,6 @@ static void keyboardHandleModifiers(void* data, uint32_t modsLocked, uint32_t group) { - xkb_mod_mask_t mask; - unsigned int modifiers = 0; - _glfw.wl.serial = serial; if (!_glfw.wl.xkb.keymap) @@ -620,24 +617,29 @@ static void keyboardHandleModifiers(void* data, 0, group); - mask = xkb_state_serialize_mods(_glfw.wl.xkb.state, - XKB_STATE_MODS_DEPRESSED | - XKB_STATE_LAYOUT_DEPRESSED | - XKB_STATE_MODS_LATCHED | - XKB_STATE_LAYOUT_LATCHED); + const xkb_mod_mask_t mask = + xkb_state_serialize_mods(_glfw.wl.xkb.state, + XKB_STATE_MODS_DEPRESSED | + XKB_STATE_LAYOUT_DEPRESSED | + XKB_STATE_MODS_LATCHED | + XKB_STATE_LAYOUT_LATCHED); + + unsigned int mods = 0; + if (mask & _glfw.wl.xkb.controlMask) - modifiers |= GLFW_MOD_CONTROL; + mods |= GLFW_MOD_CONTROL; if (mask & _glfw.wl.xkb.altMask) - modifiers |= GLFW_MOD_ALT; + mods |= GLFW_MOD_ALT; if (mask & _glfw.wl.xkb.shiftMask) - modifiers |= GLFW_MOD_SHIFT; + mods |= GLFW_MOD_SHIFT; if (mask & _glfw.wl.xkb.superMask) - modifiers |= GLFW_MOD_SUPER; + mods |= GLFW_MOD_SUPER; if (mask & _glfw.wl.xkb.capsLockMask) - modifiers |= GLFW_MOD_CAPS_LOCK; + mods |= GLFW_MOD_CAPS_LOCK; if (mask & _glfw.wl.xkb.numLockMask) - modifiers |= GLFW_MOD_NUM_LOCK; - _glfw.wl.xkb.modifiers = modifiers; + mods |= GLFW_MOD_NUM_LOCK; + + _glfw.wl.xkb.modifiers = mods; } #ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION From 7f6aa587f8a0640b055133eddf09c9a652c94234 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 2 Feb 2022 19:20:32 +0100 Subject: [PATCH 49/51] Cocoa: Fix deprecation warning for kUTTypeURL We switched to kUTTypeURL when NSURLPboardType was deprecated, as the official replacement symbol NSPasteboardTypeURL was not available on every version of macOS supported by GLFW. kUTTypeURL has now also been deprecated. This commit moves to a compile-time choice between NSURLPboardType and NSPasteboardTypeURL depending on the minimum targeted macOS version. Fixes #2003 --- CONTRIBUTORS.md | 1 + README.md | 1 + src/cocoa_platform.h | 4 ++++ src/cocoa_window.m | 4 +--- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 1bfc5bc5..cb9b0d58 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -183,6 +183,7 @@ video tutorials. - Ali Sherief - Yoshiki Shibukawa - Dmitri Shuralyov + - Daniel Sieger - Daniel Skorupski - Anthony Smith - Bradley Smith diff --git a/README.md b/README.md index 4a3fb85c..7ffd4850 100644 --- a/README.md +++ b/README.md @@ -234,6 +234,7 @@ information on what to include when reporting a bug. - [Cocoa] Bugfix: Moving the cursor programmatically would freeze it for a fraction of a second (#1962) - [Cocoa] Bugfix: `kIOMasterPortDefault` was deprecated in macOS 12.0 (#1980) + - [Cocoa] Bugfix: `kUTTypeURL` was deprecated in macOS 12.0 (#2003) - [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_platform.h b/src/cocoa_platform.h index 67c1a3cc..9d88ac4f 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -70,6 +70,10 @@ typedef void* id; #define NSWindowStyleMaskTitled NSTitledWindowMask #endif +#if MAC_OS_X_VERSION_MIN_REQUIRED < 101300 + #define NSPasteboardTypeURL NSURLPboardType +#endif + typedef VkFlags VkMacOSSurfaceCreateFlagsMVK; typedef VkFlags VkMetalSurfaceCreateFlagsEXT; diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 660bbd31..e461b267 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -361,9 +361,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; markedText = [[NSMutableAttributedString alloc] init]; [self updateTrackingAreas]; - // NOTE: kUTTypeURL corresponds to NSPasteboardTypeURL but is available - // on 10.7 without having been deprecated yet - [self registerForDraggedTypes:@[(__bridge NSString*) kUTTypeURL]]; + [self registerForDraggedTypes:@[NSPasteboardTypeURL]]; } return self; From e023618daabd43849cfc7ac4610896dc8e14be57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 2 Feb 2022 21:49:06 +0100 Subject: [PATCH 50/51] Remove Doxyfile tag deprecated by Doxygen 1.9.3 --- docs/Doxyfile.in | 9 --------- 1 file changed, 9 deletions(-) diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in index ef711cd7..812eec5d 100644 --- a/docs/Doxyfile.in +++ b/docs/Doxyfile.in @@ -2167,15 +2167,6 @@ EXTERNAL_PAGES = YES # Configuration options related to the dot tool #--------------------------------------------------------------------------- -# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram -# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to -# NO turns the diagrams off. Note that this option also works with HAVE_DOT -# disabled, but it is recommended to install and use dot, since it yields more -# powerful graphs. -# The default value is: YES. - -CLASS_DIAGRAMS = YES - # You can include diagrams made with dia in doxygen documentation. Doxygen will # then run dia to produce the diagram and insert it in the documentation. The # DIA_PATH tag allows you to specify the directory where the dia binary resides. From 97da62a027794d9ff0f4512268cb9a73a8fb5073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 2 Feb 2022 22:49:55 +0100 Subject: [PATCH 51/51] Cocoa: Clarify comments on compatibility macros --- src/cocoa_platform.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h index 9d88ac4f..9259b195 100644 --- a/src/cocoa_platform.h +++ b/src/cocoa_platform.h @@ -42,16 +42,15 @@ typedef void* id; #endif // NOTE: Many Cocoa enum values have been renamed and we need to build across -// SDK versions where one is unavailable or the other deprecated -// We use the newer names in code and these macros to handle compatibility +// SDK versions where one is unavailable or deprecated. +// We use the newer names in code and replace them with the older names if +// the base SDK does not provide the newer names. + #if MAC_OS_X_VERSION_MAX_ALLOWED < 101400 #define NSOpenGLContextParameterSwapInterval NSOpenGLCPSwapInterval #define NSOpenGLContextParameterSurfaceOpacity NSOpenGLCPSurfaceOpacity #endif -// NOTE: Many Cocoa enum values have been renamed and we need to build across -// SDK versions where one is unavailable or the other deprecated -// We use the newer names in code and these macros to handle compatibility #if MAC_OS_X_VERSION_MAX_ALLOWED < 101200 #define NSBitmapFormatAlphaNonpremultiplied NSAlphaNonpremultipliedBitmapFormat #define NSEventMaskAny NSAnyEventMask @@ -70,6 +69,11 @@ typedef void* id; #define NSWindowStyleMaskTitled NSTitledWindowMask #endif +// NOTE: Many Cocoa dynamically linked constants have been renamed and we need +// to build across SDK versions where one is unavailable or deprecated. +// We use the newer names in code and replace them with the older names if +// the deployment target is older than the newer names. + #if MAC_OS_X_VERSION_MIN_REQUIRED < 101300 #define NSPasteboardTypeURL NSURLPboardType #endif