From 7c7cd2a605a0ad84184d323d6f10d79255aac3a9 Mon Sep 17 00:00:00 2001 From: David Jacewicz Date: Mon, 17 Oct 2022 14:04:29 -0400 Subject: [PATCH] Fix issue #6037 (incorrect modifier flags on Wayland) --- src/video/wayland/SDL_waylandevents.c | 45 +++++++++++++++---------- src/video/wayland/SDL_waylandevents_c.h | 8 ----- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index fe7082417..65e829c10 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -955,16 +955,6 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, return; } - #define GET_MOD_INDEX(mod) \ - WAYLAND_xkb_keymap_mod_get_index(input->xkb.keymap, XKB_MOD_NAME_##mod) - input->xkb.idx_shift = 1 << GET_MOD_INDEX(SHIFT); - input->xkb.idx_ctrl = 1 << GET_MOD_INDEX(CTRL); - input->xkb.idx_alt = 1 << GET_MOD_INDEX(ALT); - input->xkb.idx_gui = 1 << GET_MOD_INDEX(LOGO); - input->xkb.idx_num = 1 << GET_MOD_INDEX(NUM); - input->xkb.idx_caps = 1 << GET_MOD_INDEX(CAPS); - #undef GET_MOD_INDEX - input->xkb.state = WAYLAND_xkb_state_new(input->xkb.keymap); if (!input->xkb.state) { SDL_SetError("failed to create XKB state\n"); @@ -1002,13 +992,30 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, } } + static void keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { + // Caps Lock not included because it only makes sense to consider modifiers + // that get held down, for the case where a user clicks on an unfocused + // window with a modifier key like Shift pressed, in a situation where the + // application handles Shift+click differently from a click + const SDL_Scancode mod_scancodes[] = { + SDL_SCANCODE_LSHIFT, + SDL_SCANCODE_RSHIFT, + SDL_SCANCODE_LCTRL, + SDL_SCANCODE_RCTRL, + SDL_SCANCODE_LALT, + SDL_SCANCODE_RALT, + SDL_SCANCODE_LGUI, + SDL_SCANCODE_RGUI, + }; struct SDL_WaylandInput *input = data; SDL_WindowData *window; + uint32_t *key; + SDL_Scancode scancode; if (!surface) { /* enter event for a window we've just destroyed */ @@ -1031,6 +1038,16 @@ keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, SDL_IME_SetFocus(SDL_TRUE); } #endif + + wl_array_for_each(key, keys) { + scancode = SDL_GetScancodeFromTable(SDL_SCANCODE_TABLE_XFREE86_2, *key); + for (uint32_t i = 0; i < sizeof mod_scancodes / sizeof *mod_scancodes; ++i) { + if (mod_scancodes[i] == scancode) { + SDL_SendKeyboardKey(SDL_PRESSED, scancode); + break; + } + } + } } static void @@ -1223,18 +1240,10 @@ keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, { struct SDL_WaylandInput *input = data; Wayland_Keymap keymap; - uint32_t modstate = (mods_depressed | mods_latched | mods_locked); WAYLAND_xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched, mods_locked, 0, 0, group); - SDL_ToggleModState(KMOD_SHIFT, modstate & input->xkb.idx_shift); - SDL_ToggleModState(KMOD_CTRL, modstate & input->xkb.idx_ctrl); - SDL_ToggleModState(KMOD_ALT, modstate & input->xkb.idx_alt); - SDL_ToggleModState(KMOD_GUI, modstate & input->xkb.idx_gui); - SDL_ToggleModState(KMOD_NUM, modstate & input->xkb.idx_num); - SDL_ToggleModState(KMOD_CAPS, modstate & input->xkb.idx_caps); - /* If a key is repeating, update the text to apply the modifier. */ if(keyboard_repeat_is_set(&input->keyboard_repeat)) { char text[8]; diff --git a/src/video/wayland/SDL_waylandevents_c.h b/src/video/wayland/SDL_waylandevents_c.h index 7554a9e88..f1f472633 100644 --- a/src/video/wayland/SDL_waylandevents_c.h +++ b/src/video/wayland/SDL_waylandevents_c.h @@ -110,14 +110,6 @@ struct SDL_WaylandInput { /* Keyboard layout "group" */ uint32_t current_group; - - /* Modifier bitshift values */ - uint32_t idx_shift; - uint32_t idx_ctrl; - uint32_t idx_alt; - uint32_t idx_gui; - uint32_t idx_num; - uint32_t idx_caps; } xkb; /* information about axis events on current frame */