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 01/25] 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 02/25] 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 03/25] 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 04/25] 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 05/25] 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 06/25] 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 07/25] 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 08/25] 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 09/25] 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 10/25] 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 11/25] 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 12/25] 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 13/25] 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 14/25] 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 15/25] 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 16/25] 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 17/25] 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 18/25] 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 19/25] 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 20/25] 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 21/25] 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 22/25] 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 23/25] 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 24/25] 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 25/25] 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