From d77aaa770f97cd22b16cb4c8b9a3b9aaf33da245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 13 Jul 2022 12:53:25 +0200 Subject: [PATCH 01/13] Wayland: Fix non-standard struct initialization --- src/wl_window.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index 1661d241..80c601d0 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -743,7 +743,7 @@ static GLFWbool createNativeSurface(_GLFWwindow* window, static void setCursorImage(_GLFWwindow* window, _GLFWcursorWayland* cursorWayland) { - struct itimerspec timer = {}; + struct itimerspec timer = {0}; struct wl_cursor* wlCursor = cursorWayland->cursor; struct wl_cursor_image* image; struct wl_buffer* buffer; @@ -1397,7 +1397,7 @@ static void keyboardHandleLeave(void* userData, if (!window) return; - struct itimerspec timer = {}; + struct itimerspec timer = {0}; timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL); _glfw.wl.serial = serial; @@ -1471,7 +1471,7 @@ static void keyboardHandleKey(void* userData, _glfw.wl.serial = serial; _glfwInputKey(window, key, scancode, action, _glfw.wl.xkb.modifiers); - struct itimerspec timer = {}; + struct itimerspec timer = {0}; if (action == GLFW_PRESS) { From 4df24735ef6bb644830ecdacf89dd04cd8547b86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 13 Jul 2022 14:26:25 +0200 Subject: [PATCH 02/13] Wayland: Do not emit events for destroyed window During platform window destruction, all of its callbacks have already been removed, so emitting events for it does nothing. --- src/wl_window.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index 80c601d0..8ad16cc0 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1843,15 +1843,10 @@ GLFWbool _glfwCreateWindowWayland(_GLFWwindow* window, void _glfwDestroyWindowWayland(_GLFWwindow* window) { if (window == _glfw.wl.pointerFocus) - { _glfw.wl.pointerFocus = NULL; - _glfwInputCursorEnter(window, GLFW_FALSE); - } + if (window == _glfw.wl.keyboardFocus) - { _glfw.wl.keyboardFocus = NULL; - _glfwInputWindowFocus(window, GLFW_FALSE); - } if (window->wl.idleInhibitor) zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor); From e47cb7c1e20f20b8f7d091e477be3fe41201836e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 13 Jul 2022 20:13:01 +0200 Subject: [PATCH 03/13] Wayland: Update state before emitting events --- src/wl_window.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index 8ad16cc0..df208a33 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1044,8 +1044,8 @@ static void pointerHandleLeave(void* userData, _glfw.wl.serial = serial; _glfw.wl.pointerFocus = NULL; - _glfwInputCursorEnter(window, GLFW_FALSE); _glfw.wl.cursorPreviousName = NULL; + _glfwInputCursorEnter(window, GLFW_FALSE); } static void setCursor(_GLFWwindow* window, const char* name) @@ -1116,8 +1116,8 @@ static void pointerHandleMotion(void* userData, switch (window->wl.decorations.focus) { case mainWindow: - _glfwInputCursorPos(window, x, y); _glfw.wl.cursorPreviousName = NULL; + _glfwInputCursorPos(window, x, y); return; case topDecoration: if (y < GLFW_BORDER_SIZE) From a1a73ee86257a62818b010cd3de55e10d7ce7105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 13 Jul 2022 20:33:30 +0200 Subject: [PATCH 04/13] Wayland: Make text input logic static Since the seat listener was moved into wl_window.c there is no reason for text input to have external linkage. --- src/wl_platform.h | 1 - src/wl_window.c | 101 +++++++++++++++++++++++----------------------- 2 files changed, 50 insertions(+), 52 deletions(-) diff --git a/src/wl_platform.h b/src/wl_platform.h index b85d79a5..b84aff9a 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -515,7 +515,6 @@ void _glfwSetGammaRampWayland(_GLFWmonitor* monitor, const GLFWgammaramp* ramp); void _glfwAddOutputWayland(uint32_t name, uint32_t version); void _glfwUpdateContentScaleWayland(_GLFWwindow* window); -GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode); void _glfwAddSeatListenerWayland(struct wl_seat* seat); void _glfwAddDataDeviceListenerWayland(struct wl_data_device* device); diff --git a/src/wl_window.c b/src/wl_window.c index df208a33..6e070aaf 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -821,6 +821,54 @@ static GLFWbool flushDisplay(void) return GLFW_TRUE; } +static int translateKey(uint32_t scancode) +{ + if (scancode < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0])) + return _glfw.wl.keycodes[scancode]; + + return GLFW_KEY_UNKNOWN; +} + +static xkb_keysym_t composeSymbol(xkb_keysym_t sym) +{ + if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState) + return sym; + if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym) + != XKB_COMPOSE_FEED_ACCEPTED) + return sym; + switch (xkb_compose_state_get_status(_glfw.wl.xkb.composeState)) + { + case XKB_COMPOSE_COMPOSED: + return xkb_compose_state_get_one_sym(_glfw.wl.xkb.composeState); + case XKB_COMPOSE_COMPOSING: + case XKB_COMPOSE_CANCELLED: + return XKB_KEY_NoSymbol; + case XKB_COMPOSE_NOTHING: + default: + return sym; + } +} + +GLFWbool inputText(_GLFWwindow* window, uint32_t scancode) +{ + const xkb_keysym_t* keysyms; + const xkb_keycode_t keycode = scancode + 8; + + if (xkb_state_key_get_syms(_glfw.wl.xkb.state, keycode, &keysyms) == 1) + { + const xkb_keysym_t keysym = composeSymbol(keysyms[0]); + const uint32_t codepoint = _glfwKeySym2Unicode(keysym); + if (codepoint != GLFW_INVALID_CODEPOINT) + { + const int mods = _glfw.wl.xkb.modifiers; + const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); + _glfwInputChar(window, codepoint, mods, plain); + } + } + + return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, keycode); +} + static void handleEvents(double* timeout) { GLFWbool event = GLFW_FALSE; @@ -880,8 +928,7 @@ static void handleEvents(double* timeout) _glfw.wl.keyboardLastScancode, GLFW_PRESS, _glfw.wl.xkb.modifiers); - _glfwInputTextWayland(_glfw.wl.keyboardFocus, - _glfw.wl.keyboardLastScancode); + inputText(_glfw.wl.keyboardFocus, _glfw.wl.keyboardLastScancode); } event = GLFW_TRUE; @@ -1405,54 +1452,6 @@ static void keyboardHandleLeave(void* userData, _glfwInputWindowFocus(window, GLFW_FALSE); } -static int translateKey(uint32_t scancode) -{ - if (scancode < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0])) - return _glfw.wl.keycodes[scancode]; - - return GLFW_KEY_UNKNOWN; -} - -static xkb_keysym_t composeSymbol(xkb_keysym_t sym) -{ - if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState) - return sym; - if (xkb_compose_state_feed(_glfw.wl.xkb.composeState, sym) - != XKB_COMPOSE_FEED_ACCEPTED) - return sym; - switch (xkb_compose_state_get_status(_glfw.wl.xkb.composeState)) - { - case XKB_COMPOSE_COMPOSED: - return xkb_compose_state_get_one_sym(_glfw.wl.xkb.composeState); - case XKB_COMPOSE_COMPOSING: - case XKB_COMPOSE_CANCELLED: - return XKB_KEY_NoSymbol; - case XKB_COMPOSE_NOTHING: - default: - return sym; - } -} - -GLFWbool _glfwInputTextWayland(_GLFWwindow* window, uint32_t scancode) -{ - const xkb_keysym_t* keysyms; - const xkb_keycode_t keycode = scancode + 8; - - if (xkb_state_key_get_syms(_glfw.wl.xkb.state, keycode, &keysyms) == 1) - { - const xkb_keysym_t keysym = composeSymbol(keysyms[0]); - const uint32_t codepoint = _glfwKeySym2Unicode(keysym); - if (codepoint != GLFW_INVALID_CODEPOINT) - { - const int mods = _glfw.wl.xkb.modifiers; - const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); - _glfwInputChar(window, codepoint, mods, plain); - } - } - - return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, keycode); -} - static void keyboardHandleKey(void* userData, struct wl_keyboard* keyboard, uint32_t serial, @@ -1475,7 +1474,7 @@ static void keyboardHandleKey(void* userData, if (action == GLFW_PRESS) { - const GLFWbool shouldRepeat = _glfwInputTextWayland(window, scancode); + const GLFWbool shouldRepeat = inputText(window, scancode); if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0) { From 9180923ea08d70d15a287b49a06ffbecd781a060 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 13 Jul 2022 21:32:30 +0200 Subject: [PATCH 05/13] Wayland: Clean up key repeat logic --- src/wl_init.c | 11 +++++++---- src/wl_platform.h | 10 +++++----- src/wl_window.c | 40 ++++++++++++++++++++-------------------- 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/wl_init.c b/src/wl_init.c index 2ce6f7f9..06928a04 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -478,7 +478,7 @@ int _glfwInitWayland(void) int cursorSize; // These must be set before any failure checks - _glfw.wl.timerfd = -1; + _glfw.wl.keyRepeatTimerfd = -1; _glfw.wl.cursorTimerfd = -1; _glfw.wl.client.display_flush = (PFN_wl_display_flush) @@ -639,7 +639,10 @@ int _glfwInitWayland(void) #ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION if (_glfw.wl.seatVersion >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION) - _glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); + { + _glfw.wl.keyRepeatTimerfd = + timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); + } #endif if (!_glfw.wl.wmBase) @@ -772,8 +775,8 @@ void _glfwTerminateWayland(void) wl_display_disconnect(_glfw.wl.display); } - if (_glfw.wl.timerfd >= 0) - close(_glfw.wl.timerfd); + if (_glfw.wl.keyRepeatTimerfd >= 0) + close(_glfw.wl.keyRepeatTimerfd); if (_glfw.wl.cursorTimerfd >= 0) close(_glfw.wl.cursorTimerfd); diff --git a/src/wl_platform.h b/src/wl_platform.h index b84aff9a..f65bcb11 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -322,12 +322,12 @@ typedef struct _GLFWlibraryWayland uint32_t serial; uint32_t pointerEnterSerial; - int32_t keyboardRepeatRate; - int32_t keyboardRepeatDelay; - int keyboardLastKey; - int keyboardLastScancode; + int keyRepeatTimerfd; + int32_t keyRepeatRate; + int32_t keyRepeatDelay; + int keyRepeatScancode; + char* clipboardString; - int timerfd; short int keycodes[256]; short int scancodes[GLFW_KEY_LAST + 1]; char keynames[GLFW_KEY_LAST + 1][5]; diff --git a/src/wl_window.c b/src/wl_window.c index 6e070aaf..87de85d9 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -849,7 +849,7 @@ static xkb_keysym_t composeSymbol(xkb_keysym_t sym) } } -GLFWbool inputText(_GLFWwindow* window, uint32_t scancode) +void inputText(_GLFWwindow* window, uint32_t scancode) { const xkb_keysym_t* keysyms; const xkb_keycode_t keycode = scancode + 8; @@ -865,8 +865,6 @@ GLFWbool inputText(_GLFWwindow* window, uint32_t scancode) _glfwInputChar(window, codepoint, mods, plain); } } - - return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, keycode); } static void handleEvents(double* timeout) @@ -875,7 +873,7 @@ static void handleEvents(double* timeout) struct pollfd fds[] = { { wl_display_get_fd(_glfw.wl.display), POLLIN }, - { _glfw.wl.timerfd, POLLIN }, + { _glfw.wl.keyRepeatTimerfd, POLLIN }, { _glfw.wl.cursorTimerfd, POLLIN }, }; @@ -919,16 +917,16 @@ static void handleEvents(double* timeout) { uint64_t repeats; - if (read(_glfw.wl.timerfd, &repeats, sizeof(repeats)) == 8) + if (read(_glfw.wl.keyRepeatTimerfd, &repeats, sizeof(repeats)) == 8) { for (uint64_t i = 0; i < repeats; i++) { _glfwInputKey(_glfw.wl.keyboardFocus, - _glfw.wl.keyboardLastKey, - _glfw.wl.keyboardLastScancode, + translateKey(_glfw.wl.keyRepeatScancode), + _glfw.wl.keyRepeatScancode, GLFW_PRESS, _glfw.wl.xkb.modifiers); - inputText(_glfw.wl.keyboardFocus, _glfw.wl.keyboardLastScancode); + inputText(_glfw.wl.keyboardFocus, _glfw.wl.keyRepeatScancode); } event = GLFW_TRUE; @@ -1445,7 +1443,7 @@ static void keyboardHandleLeave(void* userData, return; struct itimerspec timer = {0}; - timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL); + timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL); _glfw.wl.serial = serial; _glfw.wl.keyboardFocus = NULL; @@ -1474,23 +1472,25 @@ static void keyboardHandleKey(void* userData, if (action == GLFW_PRESS) { - const GLFWbool shouldRepeat = inputText(window, scancode); + inputText(window, scancode); - if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0) + const xkb_keycode_t keycode = scancode + 8; + + if (xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, keycode) && + _glfw.wl.keyRepeatRate > 0) { - _glfw.wl.keyboardLastKey = key; - _glfw.wl.keyboardLastScancode = scancode; - if (_glfw.wl.keyboardRepeatRate > 1) - timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyboardRepeatRate; + _glfw.wl.keyRepeatScancode = scancode; + if (_glfw.wl.keyRepeatRate > 1) + timer.it_interval.tv_nsec = 1000000000 / _glfw.wl.keyRepeatRate; 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; + timer.it_value.tv_sec = _glfw.wl.keyRepeatDelay / 1000; + timer.it_value.tv_nsec = (_glfw.wl.keyRepeatDelay % 1000) * 1000000; } } - timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL); + timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL); } static void keyboardHandleModifiers(void* userData, @@ -1550,8 +1550,8 @@ static void keyboardHandleRepeatInfo(void* userData, if (keyboard != _glfw.wl.keyboard) return; - _glfw.wl.keyboardRepeatRate = rate; - _glfw.wl.keyboardRepeatDelay = delay; + _glfw.wl.keyRepeatRate = rate; + _glfw.wl.keyRepeatDelay = delay; } #endif From 40b5a8a37cb4770ff5d307beb660fadc64be1265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 13 Jul 2022 12:54:24 +0200 Subject: [PATCH 06/13] Wayland: Fix reappearing key repeat If the key or character callback performs actions that indirectly updates the key repeat timer, those changes would be undone once the key callback returned. This fixes the order of operations so that key repeat is fully set up before the key related events are emitted. --- src/wl_window.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index 87de85d9..16491cde 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -1466,14 +1466,11 @@ static void keyboardHandleKey(void* userData, state == WL_KEYBOARD_KEY_STATE_PRESSED ? GLFW_PRESS : GLFW_RELEASE; _glfw.wl.serial = serial; - _glfwInputKey(window, key, scancode, action, _glfw.wl.xkb.modifiers); struct itimerspec timer = {0}; if (action == GLFW_PRESS) { - inputText(window, scancode); - const xkb_keycode_t keycode = scancode + 8; if (xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, keycode) && @@ -1491,6 +1488,11 @@ static void keyboardHandleKey(void* userData, } timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL); + + _glfwInputKey(window, key, scancode, action, _glfw.wl.xkb.modifiers); + + if (action == GLFW_PRESS) + inputText(window, scancode); } static void keyboardHandleModifiers(void* userData, From c50d53160fa9b579dda0d0a4f9a7c2512940df8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 13 Jul 2022 21:46:14 +0200 Subject: [PATCH 07/13] Make events test window appear on Wayland --- tests/events.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/events.c b/tests/events.c index a9d4023d..60d4fc89 100644 --- a/tests/events.c +++ b/tests/events.c @@ -642,7 +642,7 @@ int main(int argc, char** argv) glfwMakeContextCurrent(slots[i].window); gladLoadGL(glfwGetProcAddress); - glfwSwapInterval(1); + glfwSwapBuffers(slots[i].window); } printf("Main loop starting\n"); From c424fe55892e7ac7c849989b9ab5e143825fdd4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Hempel?= Date: Sun, 6 Feb 2022 13:32:10 +0100 Subject: [PATCH 08/13] Linux: Fix joystick without buttons being ignored Joysticks in Linux without buttons were ignored by device enumeration. Remove the mandatory button attribute from detection. Fixes #2042 Closes #2043 --- src/linux_joystick.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linux_joystick.c b/src/linux_joystick.c index fd5dabdf..366bda2d 100644 --- a/src/linux_joystick.c +++ b/src/linux_joystick.c @@ -157,7 +157,7 @@ static GLFWbool openJoystickDevice(const char* path) } // Ensure this device supports the events expected of a joystick - if (!isBitSet(EV_KEY, evBits) || !isBitSet(EV_ABS, evBits)) + if (!isBitSet(EV_ABS, evBits)) { close(linjs.fd); return GLFW_FALSE; From 91a96ed4343944add92bc02619319bb9ae9379fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Fri, 15 Jul 2022 15:54:35 +0200 Subject: [PATCH 09/13] Update changelog and add credit Related to #2042 Related to #2043 --- CONTRIBUTORS.md | 1 + README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 2548dea2..153c38d2 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -82,6 +82,7 @@ video tutorials. - Jonathan Hale - hdf89shfdfs - Sylvain Hellegouarch + - Björn Hempel - Matthew Henry - heromyth - Lucas Hinderberger diff --git a/README.md b/README.md index 452577de..b0405480 100644 --- a/README.md +++ b/README.md @@ -374,6 +374,7 @@ information on what to include when reporting a bug. decorations - [POSIX] Removed use of deprecated function `gettimeofday` - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled + - [Linux] Bugfix: Joysticks without buttons were ignored (#2042,#2043) - [WGL] Disabled the DWM swap interval hack for Windows 8 and later (#1072) - [NSGL] Removed enforcement of forward-compatible flag for core contexts - [NSGL] Bugfix: `GLFW_COCOA_RETINA_FRAMEBUFFER` had no effect on newer From 7cc8b053b81ecbb32c013d47b8554c0ed116c820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Fri, 15 Jul 2022 12:50:18 +0200 Subject: [PATCH 10/13] Wayland: Clean up shared memory buffer creation --- src/wl_window.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/wl_window.c b/src/wl_window.c index 16491cde..5df692e3 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -142,11 +142,8 @@ static int createAnonymousFile(off_t size) static struct wl_buffer* createShmBuffer(const GLFWimage* image) { - struct wl_shm_pool* pool; - struct wl_buffer* buffer; - int stride = image->width * 4; - int length = image->width * image->height * 4; - void* data; + const int stride = image->width * 4; + const int length = image->width * image->height * 4; const int fd = createAnonymousFile(length); if (fd < 0) @@ -157,7 +154,7 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image) return NULL; } - data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + void* data = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (data == MAP_FAILED) { _glfwInputError(GLFW_PLATFORM_ERROR, @@ -166,9 +163,10 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image) return NULL; } - pool = wl_shm_create_pool(_glfw.wl.shm, fd, length); + struct wl_shm_pool* pool = wl_shm_create_pool(_glfw.wl.shm, fd, length); close(fd); + unsigned char* source = (unsigned char*) image->pixels; unsigned char* target = data; for (int i = 0; i < image->width * image->height; i++, source += 4) @@ -181,7 +179,7 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image) *target++ = (unsigned char) alpha; } - buffer = + struct wl_buffer* buffer = wl_shm_pool_create_buffer(pool, 0, image->width, image->height, From 71be34a6c30825aef502b652c86cc31fdcbb5457 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Fri, 15 Jul 2022 13:12:58 +0200 Subject: [PATCH 11/13] Wayland: Fix crash if mouse connected after init The cursor theme was only loaded if the chosen seat had a mouse (wl_pointer) during initialization. If a mouse was connected only after glfwInit, there would be no cursor theme but the rest of the cursor related code assumed one had already been loaded. This also moves the details of cursor theme loading out into a separate function to declutter platform init. Because the original cursor theme loading code checked whether we got a wl_shm, and because the rest of the code just assumes we have a wl_shm, initialization will now fail if there isn't one. Fixes #1450 --- CONTRIBUTORS.md | 1 + README.md | 1 + src/wl_init.c | 73 ++++++++++++++++++++++++++++--------------------- 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 153c38d2..673db319 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -187,6 +187,7 @@ video tutorials. - Philip Rideout - Eddie Ringle - Max Risuhin + - Joe Roback - Jorge Rodriguez - Jari Ronkainen - Luca Rood diff --git a/README.md b/README.md index b0405480..5b56b3eb 100644 --- a/README.md +++ b/README.md @@ -372,6 +372,7 @@ information on what to include when reporting a bug. wlroots compositors (#1268) - [Wayland] Bugfix: `GLFW_DECORATED` was ignored when showing a window with XDG decorations + - [Wayland] Bugfix: Connecting a mouse after `glfwInit` would segfault (#1450) - [POSIX] Removed use of deprecated function `gettimeofday` - [POSIX] Bugfix: `CLOCK_MONOTONIC` was not correctly tested for or enabled - [Linux] Bugfix: Joysticks without buttons were ignored (#2042,#2043) diff --git a/src/wl_init.c b/src/wl_init.c index 06928a04..3883b405 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -335,6 +335,41 @@ static void createKeyTables(void) } } +static GLFWbool loadCursorTheme(void) +{ + const char* cursorTheme; + const char* cursorSizeStr; + char* cursorSizeEnd; + long cursorSizeLong; + int cursorSize; + + cursorTheme = getenv("XCURSOR_THEME"); + cursorSizeStr = getenv("XCURSOR_SIZE"); + cursorSize = 32; + if (cursorSizeStr) + { + errno = 0; + cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10); + if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX) + cursorSize = (int)cursorSizeLong; + } + _glfw.wl.cursorTheme = + wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm); + if (!_glfw.wl.cursorTheme) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to load default cursor theme"); + return GLFW_FALSE; + } + // If this happens to be NULL, we just fallback to the scale=1 version. + _glfw.wl.cursorThemeHiDPI = + 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 | TFD_NONBLOCK); + return GLFW_TRUE; +} + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// @@ -471,12 +506,6 @@ GLFWbool _glfwConnectWayland(int platformID, _GLFWplatform* platform) int _glfwInitWayland(void) { - const char* cursorTheme; - const char* cursorSizeStr; - char* cursorSizeEnd; - long cursorSizeLong; - int cursorSize; - // These must be set before any failure checks _glfw.wl.keyRepeatTimerfd = -1; _glfw.wl.cursorTimerfd = -1; @@ -652,34 +681,16 @@ int _glfwInitWayland(void) return GLFW_FALSE; } - if (_glfw.wl.pointer && _glfw.wl.shm) + if (!_glfw.wl.shm) { - cursorTheme = getenv("XCURSOR_THEME"); - cursorSizeStr = getenv("XCURSOR_SIZE"); - cursorSize = 32; - if (cursorSizeStr) - { - errno = 0; - cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10); - if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX) - cursorSize = (int)cursorSizeLong; - } - _glfw.wl.cursorTheme = - wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm); - if (!_glfw.wl.cursorTheme) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Failed to load default cursor theme"); - return GLFW_FALSE; - } - // If this happens to be NULL, we just fallback to the scale=1 version. - _glfw.wl.cursorThemeHiDPI = - 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 | TFD_NONBLOCK); + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to find wl_shm in your compositor"); + return GLFW_FALSE; } + if (!loadCursorTheme()) + return GLFW_FALSE; + if (_glfw.wl.seat && _glfw.wl.dataDeviceManager) { _glfw.wl.dataDevice = From 6987294df91d9b9be03a796174863cb9d1a06d62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Fri, 15 Jul 2022 13:30:14 +0200 Subject: [PATCH 12/13] Wayland: Clean up cursor theme loading --- src/wl_init.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/wl_init.c b/src/wl_init.c index 3883b405..8cbcc6e8 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -337,35 +337,32 @@ static void createKeyTables(void) static GLFWbool loadCursorTheme(void) { - const char* cursorTheme; - const char* cursorSizeStr; - char* cursorSizeEnd; - long cursorSizeLong; - int cursorSize; + int cursorSize = 32; - cursorTheme = getenv("XCURSOR_THEME"); - cursorSizeStr = getenv("XCURSOR_SIZE"); - cursorSize = 32; - if (cursorSizeStr) + const char* sizeString = getenv("XCURSOR_SIZE"); + if (sizeString) { errno = 0; - cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10); - if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX) - cursorSize = (int)cursorSizeLong; + const long cursorSizeLong = strtol(sizeString, NULL, 10); + if (errno == 0 && cursorSizeLong > 0 && cursorSizeLong < INT_MAX) + cursorSize = (int) cursorSizeLong; } - _glfw.wl.cursorTheme = - wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm); + + const char* themeName = getenv("XCURSOR_THEME"); + + _glfw.wl.cursorTheme = wl_cursor_theme_load(themeName, cursorSize, _glfw.wl.shm); if (!_glfw.wl.cursorTheme) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: Failed to load default cursor theme"); return GLFW_FALSE; } + // If this happens to be NULL, we just fallback to the scale=1 version. _glfw.wl.cursorThemeHiDPI = - wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm); - _glfw.wl.cursorSurface = - wl_compositor_create_surface(_glfw.wl.compositor); + wl_cursor_theme_load(themeName, cursorSize * 2, _glfw.wl.shm); + + _glfw.wl.cursorSurface = wl_compositor_create_surface(_glfw.wl.compositor); _glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); return GLFW_TRUE; } From 26b85215c07a32f860326bf02ef68f31c5e30837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Thu, 14 Jul 2022 11:52:55 +0200 Subject: [PATCH 13/13] Wayland: Static function more static when static --- src/wl_window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wl_window.c b/src/wl_window.c index 5df692e3..ef935d33 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -847,7 +847,7 @@ static xkb_keysym_t composeSymbol(xkb_keysym_t sym) } } -void inputText(_GLFWwindow* window, uint32_t scancode) +static void inputText(_GLFWwindow* window, uint32_t scancode) { const xkb_keysym_t* keysyms; const xkb_keycode_t keycode = scancode + 8;