SDL: wayland: Use xkb_keymap_mod to set mod state

From 2891f0821b27012242c30759308bd8eed83d3fe7 Mon Sep 17 00:00:00 2001
From: Ethan Lee <[EMAIL REDACTED]>
Date: Fri, 25 Mar 2022 02:49:49 -0400
Subject: [PATCH] wayland: Use xkb_keymap_mod to set mod state

---
 src/video/wayland/SDL_waylandevents.c | 36 ++++++++++++---------------
 src/video/wayland/SDL_waylandsym.h    |  2 ++
 2 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index fbab0601fab..b5d4ad1cd9c 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -910,8 +910,6 @@ keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint
     SDL_WindowData *window = input->keyboard_focus;
     const xkb_keysym_t *syms;
     xkb_keysym_t sym;
-    SDL_Keymod mod;
-    SDL_bool caps;
 
     if (!window || window->keyboard_device != input || !input->xkb.state) {
         return SDL_FALSE;
@@ -923,24 +921,6 @@ keyboard_input_get_text(char text[8], const struct SDL_WaylandInput *input, uint
     }
     sym = syms[0];
 
-    /* Wayland is actually pretty cool and sends key codes based on presumed
-     * caps lock state, problem is that it isn't totally accurate if the key
-     * has been remapped, so we have to force caps for our purposes.
-     * -flibit
-     */
-    mod = SDL_GetModState();
-    caps = (
-        /* Caps lock without shift... */
-        ((mod & KMOD_CAPS) && !(mod & KMOD_SHIFT)) ||
-        /* No caps lock with shift... */
-        (!(mod & KMOD_CAPS) && (mod & KMOD_SHIFT))
-    );
-    if (caps) {
-        sym = toupper(sym);
-    } else {
-        sym = tolower(sym);
-    }
-
 #ifdef SDL_USE_IME
     if (SDL_IME_ProcessKeyEvent(sym, key + 8)) {
         *handled_by_ime = SDL_TRUE;
@@ -1076,10 +1056,26 @@ keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
 {
     struct SDL_WaylandInput *input = data;
     Wayland_Keymap keymap;
+    xkb_mod_index_t shift, ctrl, alt, gui, num, caps;
+    uint32_t modstate = (mods_depressed | mods_latched | mods_locked);
+
+    shift = WAYLAND_xkb_keymap_mod_get_index(input->xkb.keymap, XKB_MOD_NAME_SHIFT);
+    ctrl = WAYLAND_xkb_keymap_mod_get_index(input->xkb.keymap, XKB_MOD_NAME_CTRL);
+    alt = WAYLAND_xkb_keymap_mod_get_index(input->xkb.keymap, XKB_MOD_NAME_ALT);
+    gui = WAYLAND_xkb_keymap_mod_get_index(input->xkb.keymap, XKB_MOD_NAME_LOGO);
+    num = WAYLAND_xkb_keymap_mod_get_index(input->xkb.keymap, XKB_MOD_NAME_NUM);
+    caps = WAYLAND_xkb_keymap_mod_get_index(input->xkb.keymap, XKB_MOD_NAME_CAPS);
 
     WAYLAND_xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched,
                           mods_locked, 0, 0, group);
 
+    SDL_ToggleModState(KMOD_SHIFT, modstate & (1 << shift));
+    SDL_ToggleModState(KMOD_CTRL, modstate & (1 << ctrl));
+    SDL_ToggleModState(KMOD_CAPS, modstate & (1 << alt));
+    SDL_ToggleModState(KMOD_GUI, modstate & (1 << gui));
+    SDL_ToggleModState(KMOD_NUM, modstate & (1 << num));
+    SDL_ToggleModState(KMOD_CAPS, modstate & (1 << caps));
+
     keymap.layout = group;
     SDL_GetDefaultKeymap(keymap.keymap);
     WAYLAND_xkb_keymap_key_for_each(input->xkb.keymap,
diff --git a/src/video/wayland/SDL_waylandsym.h b/src/video/wayland/SDL_waylandsym.h
index 35f4dc870a4..6891325c7d8 100644
--- a/src/video/wayland/SDL_waylandsym.h
+++ b/src/video/wayland/SDL_waylandsym.h
@@ -147,6 +147,8 @@ SDL_WAYLAND_SYM(int, xkb_keymap_key_get_syms_by_level, (struct xkb_keymap *,
                                                         xkb_layout_index_t,
                                                         const xkb_keysym_t **) )
 SDL_WAYLAND_SYM(uint32_t, xkb_keysym_to_utf32, (xkb_keysym_t) )
+SDL_WAYLAND_SYM(uint32_t, xkb_keymap_mod_get_index, (struct xkb_keymap *,
+                                                      const char *) )
 
 #ifdef HAVE_LIBDECOR_H
 SDL_WAYLAND_MODULE(WAYLAND_LIBDECOR)