From e64034952b2a8f8356895b56aa06645382395a18 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Fri, 21 Aug 2026 22:22:04 -0700 Subject: [PATCH] [emscripten] Remove deprecated keyEvent fields (keyCode, charCode) Backport the keyboard handling approach from SDL3 (commit 109f26897297e7af3149591a0d73e2d7dd8370be). Avoid using deprecated keyEvent->keyCode, charCode, and the emscripten_keycode_table. Instead decode UTF-8 keyEvent->key to determine the keycode and text input. --- src/video/emscripten/SDL_emscriptenevents.c | 376 +++----------------- 1 file changed, 43 insertions(+), 333 deletions(-) diff --git a/src/video/emscripten/SDL_emscriptenevents.c b/src/video/emscripten/SDL_emscriptenevents.c index 3b673b137e..f37d2911d1 100644 --- a/src/video/emscripten/SDL_emscriptenevents.c +++ b/src/video/emscripten/SDL_emscriptenevents.c @@ -38,236 +38,7 @@ #define FULLSCREEN_MASK ( SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN ) -/* -.keyCode to SDL keycode -https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent -https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode -*/ -static const SDL_Keycode emscripten_keycode_table[] = { - /* 0 */ SDLK_UNKNOWN, - /* 1 */ SDLK_UNKNOWN, - /* 2 */ SDLK_UNKNOWN, - /* 3 */ SDLK_CANCEL, - /* 4 */ SDLK_UNKNOWN, - /* 5 */ SDLK_UNKNOWN, - /* 6 */ SDLK_HELP, - /* 7 */ SDLK_UNKNOWN, - /* 8 */ SDLK_BACKSPACE, - /* 9 */ SDLK_TAB, - /* 10 */ SDLK_UNKNOWN, - /* 11 */ SDLK_UNKNOWN, - /* 12 */ SDLK_KP_5, - /* 13 */ SDLK_RETURN, - /* 14 */ SDLK_UNKNOWN, - /* 15 */ SDLK_UNKNOWN, - /* 16 */ SDLK_LSHIFT, - /* 17 */ SDLK_LCTRL, - /* 18 */ SDLK_LALT, - /* 19 */ SDLK_PAUSE, - /* 20 */ SDLK_CAPSLOCK, - /* 21 */ SDLK_UNKNOWN, - /* 22 */ SDLK_UNKNOWN, - /* 23 */ SDLK_UNKNOWN, - /* 24 */ SDLK_UNKNOWN, - /* 25 */ SDLK_UNKNOWN, - /* 26 */ SDLK_UNKNOWN, - /* 27 */ SDLK_ESCAPE, - /* 28 */ SDLK_UNKNOWN, - /* 29 */ SDLK_UNKNOWN, - /* 30 */ SDLK_UNKNOWN, - /* 31 */ SDLK_UNKNOWN, - /* 32 */ SDLK_SPACE, - /* 33 */ SDLK_PAGEUP, - /* 34 */ SDLK_PAGEDOWN, - /* 35 */ SDLK_END, - /* 36 */ SDLK_HOME, - /* 37 */ SDLK_LEFT, - /* 38 */ SDLK_UP, - /* 39 */ SDLK_RIGHT, - /* 40 */ SDLK_DOWN, - /* 41 */ SDLK_UNKNOWN, - /* 42 */ SDLK_UNKNOWN, - /* 43 */ SDLK_UNKNOWN, - /* 44 */ SDLK_UNKNOWN, - /* 45 */ SDLK_INSERT, - /* 46 */ SDLK_DELETE, - /* 47 */ SDLK_UNKNOWN, - /* 48 */ SDLK_0, - /* 49 */ SDLK_1, - /* 50 */ SDLK_2, - /* 51 */ SDLK_3, - /* 52 */ SDLK_4, - /* 53 */ SDLK_5, - /* 54 */ SDLK_6, - /* 55 */ SDLK_7, - /* 56 */ SDLK_8, - /* 57 */ SDLK_9, - /* 58 */ SDLK_UNKNOWN, - /* 59 */ SDLK_SEMICOLON, - /* 60 */ SDLK_BACKSLASH /*SDL_SCANCODE_NONUSBACKSLASH*/, - /* 61 */ SDLK_EQUALS, - /* 62 */ SDLK_UNKNOWN, - /* 63 */ SDLK_MINUS, - /* 64 */ SDLK_UNKNOWN, - /* 65 */ SDLK_a, - /* 66 */ SDLK_b, - /* 67 */ SDLK_c, - /* 68 */ SDLK_d, - /* 69 */ SDLK_e, - /* 70 */ SDLK_f, - /* 71 */ SDLK_g, - /* 72 */ SDLK_h, - /* 73 */ SDLK_i, - /* 74 */ SDLK_j, - /* 75 */ SDLK_k, - /* 76 */ SDLK_l, - /* 77 */ SDLK_m, - /* 78 */ SDLK_n, - /* 79 */ SDLK_o, - /* 80 */ SDLK_p, - /* 81 */ SDLK_q, - /* 82 */ SDLK_r, - /* 83 */ SDLK_s, - /* 84 */ SDLK_t, - /* 85 */ SDLK_u, - /* 86 */ SDLK_v, - /* 87 */ SDLK_w, - /* 88 */ SDLK_x, - /* 89 */ SDLK_y, - /* 90 */ SDLK_z, - /* 91 */ SDLK_LGUI, - /* 92 */ SDLK_UNKNOWN, - /* 93 */ SDLK_APPLICATION, - /* 94 */ SDLK_UNKNOWN, - /* 95 */ SDLK_UNKNOWN, - /* 96 */ SDLK_KP_0, - /* 97 */ SDLK_KP_1, - /* 98 */ SDLK_KP_2, - /* 99 */ SDLK_KP_3, - /* 100 */ SDLK_KP_4, - /* 101 */ SDLK_KP_5, - /* 102 */ SDLK_KP_6, - /* 103 */ SDLK_KP_7, - /* 104 */ SDLK_KP_8, - /* 105 */ SDLK_KP_9, - /* 106 */ SDLK_KP_MULTIPLY, - /* 107 */ SDLK_KP_PLUS, - /* 108 */ SDLK_UNKNOWN, - /* 109 */ SDLK_KP_MINUS, - /* 110 */ SDLK_KP_PERIOD, - /* 111 */ SDLK_KP_DIVIDE, - /* 112 */ SDLK_F1, - /* 113 */ SDLK_F2, - /* 114 */ SDLK_F3, - /* 115 */ SDLK_F4, - /* 116 */ SDLK_F5, - /* 117 */ SDLK_F6, - /* 118 */ SDLK_F7, - /* 119 */ SDLK_F8, - /* 120 */ SDLK_F9, - /* 121 */ SDLK_F10, - /* 122 */ SDLK_F11, - /* 123 */ SDLK_F12, - /* 124 */ SDLK_F13, - /* 125 */ SDLK_F14, - /* 126 */ SDLK_F15, - /* 127 */ SDLK_F16, - /* 128 */ SDLK_F17, - /* 129 */ SDLK_F18, - /* 130 */ SDLK_F19, - /* 131 */ SDLK_F20, - /* 132 */ SDLK_F21, - /* 133 */ SDLK_F22, - /* 134 */ SDLK_F23, - /* 135 */ SDLK_F24, - /* 136 */ SDLK_UNKNOWN, - /* 137 */ SDLK_UNKNOWN, - /* 138 */ SDLK_UNKNOWN, - /* 139 */ SDLK_UNKNOWN, - /* 140 */ SDLK_UNKNOWN, - /* 141 */ SDLK_UNKNOWN, - /* 142 */ SDLK_UNKNOWN, - /* 143 */ SDLK_UNKNOWN, - /* 144 */ SDLK_NUMLOCKCLEAR, - /* 145 */ SDLK_SCROLLLOCK, - /* 146 */ SDLK_UNKNOWN, - /* 147 */ SDLK_UNKNOWN, - /* 148 */ SDLK_UNKNOWN, - /* 149 */ SDLK_UNKNOWN, - /* 150 */ SDLK_UNKNOWN, - /* 151 */ SDLK_UNKNOWN, - /* 152 */ SDLK_UNKNOWN, - /* 153 */ SDLK_UNKNOWN, - /* 154 */ SDLK_UNKNOWN, - /* 155 */ SDLK_UNKNOWN, - /* 156 */ SDLK_UNKNOWN, - /* 157 */ SDLK_UNKNOWN, - /* 158 */ SDLK_UNKNOWN, - /* 159 */ SDLK_UNKNOWN, - /* 160 */ SDLK_BACKQUOTE, - /* 161 */ SDLK_UNKNOWN, - /* 162 */ SDLK_UNKNOWN, - /* 163 */ SDLK_KP_HASH, /*KaiOS phone keypad*/ - /* 164 */ SDLK_UNKNOWN, - /* 165 */ SDLK_UNKNOWN, - /* 166 */ SDLK_UNKNOWN, - /* 167 */ SDLK_UNKNOWN, - /* 168 */ SDLK_UNKNOWN, - /* 169 */ SDLK_UNKNOWN, - /* 170 */ SDLK_KP_MULTIPLY, /*KaiOS phone keypad*/ - /* 171 */ SDLK_RIGHTBRACKET, - /* 172 */ SDLK_UNKNOWN, - /* 173 */ SDLK_MINUS, /*FX*/ - /* 174 */ SDLK_VOLUMEDOWN, /*IE, Chrome*/ - /* 175 */ SDLK_VOLUMEUP, /*IE, Chrome*/ - /* 176 */ SDLK_AUDIONEXT, /*IE, Chrome*/ - /* 177 */ SDLK_AUDIOPREV, /*IE, Chrome*/ - /* 178 */ SDLK_UNKNOWN, - /* 179 */ SDLK_AUDIOPLAY, /*IE, Chrome*/ - /* 180 */ SDLK_UNKNOWN, - /* 181 */ SDLK_AUDIOMUTE, /*FX*/ - /* 182 */ SDLK_VOLUMEDOWN, /*FX*/ - /* 183 */ SDLK_VOLUMEUP, /*FX*/ - /* 184 */ SDLK_UNKNOWN, - /* 185 */ SDLK_UNKNOWN, - /* 186 */ SDLK_SEMICOLON, /*IE, Chrome, D3E legacy*/ - /* 187 */ SDLK_EQUALS, /*IE, Chrome, D3E legacy*/ - /* 188 */ SDLK_COMMA, - /* 189 */ SDLK_MINUS, /*IE, Chrome, D3E legacy*/ - /* 190 */ SDLK_PERIOD, - /* 191 */ SDLK_SLASH, - /* 192 */ SDLK_BACKQUOTE, /*FX, D3E legacy (SDLK_APOSTROPHE in IE/Chrome)*/ - /* 193 */ SDLK_UNKNOWN, - /* 194 */ SDLK_UNKNOWN, - /* 195 */ SDLK_UNKNOWN, - /* 196 */ SDLK_UNKNOWN, - /* 197 */ SDLK_UNKNOWN, - /* 198 */ SDLK_UNKNOWN, - /* 199 */ SDLK_UNKNOWN, - /* 200 */ SDLK_UNKNOWN, - /* 201 */ SDLK_UNKNOWN, - /* 202 */ SDLK_UNKNOWN, - /* 203 */ SDLK_UNKNOWN, - /* 204 */ SDLK_UNKNOWN, - /* 205 */ SDLK_UNKNOWN, - /* 206 */ SDLK_UNKNOWN, - /* 207 */ SDLK_UNKNOWN, - /* 208 */ SDLK_UNKNOWN, - /* 209 */ SDLK_UNKNOWN, - /* 210 */ SDLK_UNKNOWN, - /* 211 */ SDLK_UNKNOWN, - /* 212 */ SDLK_UNKNOWN, - /* 213 */ SDLK_UNKNOWN, - /* 214 */ SDLK_UNKNOWN, - /* 215 */ SDLK_UNKNOWN, - /* 216 */ SDLK_UNKNOWN, - /* 217 */ SDLK_UNKNOWN, - /* 218 */ SDLK_UNKNOWN, - /* 219 */ SDLK_LEFTBRACKET, - /* 220 */ SDLK_BACKSLASH, - /* 221 */ SDLK_RIGHTBRACKET, - /* 222 */ SDLK_QUOTE, /*FX, D3E legacy*/ -}; + /* Emscripten PK code to scancode @@ -501,107 +272,34 @@ static SDL_Scancode Emscripten_MapScanCode(const char *code) return SDL_SCANCODE_UNKNOWN; } -static SDL_Keycode Emscripten_MapKeyCode(const EmscriptenKeyboardEvent *keyEvent) +static Uint32 Emscripten_DecodeUTF8(const char *str) { - SDL_Keycode keycode = SDLK_UNKNOWN; - if (keyEvent->keyCode < SDL_arraysize(emscripten_keycode_table)) { - keycode = emscripten_keycode_table[keyEvent->keyCode]; - if (keycode != SDLK_UNKNOWN) { - if (keyEvent->location == DOM_KEY_LOCATION_RIGHT) { - switch (keycode) { - case SDLK_LSHIFT: - keycode = SDLK_RSHIFT; - break; - case SDLK_LCTRL: - keycode = SDLK_RCTRL; - break; - case SDLK_LALT: - keycode = SDLK_RALT; - break; - case SDLK_LGUI: - keycode = SDLK_RGUI; - break; - } - } else if (keyEvent->location == DOM_KEY_LOCATION_NUMPAD) { - switch (keycode) { - case SDLK_0: - case SDLK_INSERT: - keycode = SDLK_KP_0; - break; - case SDLK_1: - case SDLK_END: - keycode = SDLK_KP_1; - break; - case SDLK_2: - case SDLK_DOWN: - keycode = SDLK_KP_2; - break; - case SDLK_3: - case SDLK_PAGEDOWN: - keycode = SDLK_KP_3; - break; - case SDLK_4: - case SDLK_LEFT: - keycode = SDLK_KP_4; - break; - case SDLK_5: - keycode = SDLK_KP_5; - break; - case SDLK_6: - case SDLK_RIGHT: - keycode = SDLK_KP_6; - break; - case SDLK_7: - case SDLK_HOME: - keycode = SDLK_KP_7; - break; - case SDLK_8: - case SDLK_UP: - keycode = SDLK_KP_8; - break; - case SDLK_9: - case SDLK_PAGEUP: - keycode = SDLK_KP_9; - break; - case SDLK_RETURN: - keycode = SDLK_KP_ENTER; - break; - case SDLK_DELETE: - keycode = SDLK_KP_PERIOD; - break; - } - } + Uint8 octet = (Uint8)*str; + if (octet == 0) { + return 0; + } + if ((octet & 0x80) == 0) { + return octet; + } else if ((octet & 0xE0) == 0xC0) { + Uint8 str1 = (Uint8)str[1]; + if ((str1 & 0xC0) == 0x80) { + return ((octet & 0x1F) << 6) | (str1 & 0x3F); + } + } else if ((octet & 0xF0) == 0xE0) { + Uint8 str1 = (Uint8)str[1]; + Uint8 str2 = (Uint8)str[2]; + if (((str1 & 0xC0) == 0x80) && ((str2 & 0xC0) == 0x80)) { + return (((Uint32)(octet & 0x0F)) << 12) | (((Uint32)(str1 & 0x3F)) << 6) | ((Uint32)(str2 & 0x3F)); + } + } else if ((octet & 0xF8) == 0xF0) { + Uint8 str1 = (Uint8)str[1]; + Uint8 str2 = (Uint8)str[2]; + Uint8 str3 = (Uint8)str[3]; + if (((str1 & 0xC0) == 0x80) && ((str2 & 0xC0) == 0x80) && ((str3 & 0xC0) == 0x80)) { + return (((Uint32)(octet & 0x07)) << 18) | (((Uint32)(str1 & 0x3F)) << 12) | (((Uint32)(str2 & 0x3F)) << 6) | ((Uint32)(str3 & 0x3F)); } } - - return keycode; -} - -/* "borrowed" from SDL_windowsevents.c */ -static int Emscripten_ConvertUTF32toUTF8(Uint32 codepoint, char *text) -{ - if (codepoint <= 0x7F) { - text[0] = (char)codepoint; - text[1] = '\0'; - } else if (codepoint <= 0x7FF) { - text[0] = 0xC0 | (char)((codepoint >> 6) & 0x1F); - text[1] = 0x80 | (char)(codepoint & 0x3F); - text[2] = '\0'; - } else if (codepoint <= 0xFFFF) { - text[0] = 0xE0 | (char)((codepoint >> 12) & 0x0F); - text[1] = 0x80 | (char)((codepoint >> 6) & 0x3F); - text[2] = 0x80 | (char)(codepoint & 0x3F); - text[3] = '\0'; - } else if (codepoint <= 0x10FFFF) { - text[0] = 0xF0 | (char)((codepoint >> 18) & 0x0F); - text[1] = 0x80 | (char)((codepoint >> 12) & 0x3F); - text[2] = 0x80 | (char)((codepoint >> 6) & 0x3F); - text[3] = 0x80 | (char)(codepoint & 0x3F); - text[4] = '\0'; - } else { - return SDL_FALSE; - } - return SDL_TRUE; + return 0; } static EM_BOOL Emscripten_HandlePointerLockChange(int eventType, const EmscriptenPointerlockChangeEvent *changeEvent, void *userData) @@ -810,8 +508,8 @@ static SDL_bool IsFunctionKey(SDL_Scancode scancode) */ static EM_BOOL Emscripten_HandleKey(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData) { - const SDL_Keycode keycode = Emscripten_MapKeyCode(keyEvent); SDL_Scancode scancode = Emscripten_MapScanCode(keyEvent->code); + SDL_Keycode keycode = SDLK_UNKNOWN; SDL_bool prevent_default = SDL_FALSE; SDL_bool is_nav_key = SDL_FALSE; @@ -824,8 +522,19 @@ static EM_BOOL Emscripten_HandleKey(int eventType, const EmscriptenKeyboardEvent } } + if (keyEvent->location == 0 && SDL_utf8strlen(keyEvent->key) == 1) { + keycode = Emscripten_DecodeUTF8(keyEvent->key); + if (keycode >= 'A' && keycode <= 'Z') { + keycode = SDL_tolower(keycode); + } + } + if (scancode != SDL_SCANCODE_UNKNOWN) { - prevent_default = SDL_SendKeyboardKeyAndKeycode(eventType == EMSCRIPTEN_EVENT_KEYDOWN ? SDL_PRESSED : SDL_RELEASED, scancode, keycode); + if (keycode != SDLK_UNKNOWN) { + prevent_default = SDL_SendKeyboardKeyAndKeycode(eventType == EMSCRIPTEN_EVENT_KEYDOWN ? SDL_PRESSED : SDL_RELEASED, scancode, keycode); + } else { + prevent_default = SDL_SendKeyboardKey(eventType == EMSCRIPTEN_EVENT_KEYDOWN ? SDL_PRESSED : SDL_RELEASED, scancode); + } } /* if TEXTINPUT events are enabled we can't prevent keydown or we won't get keypress @@ -851,9 +560,10 @@ static EM_BOOL Emscripten_HandleKey(int eventType, const EmscriptenKeyboardEvent static EM_BOOL Emscripten_HandleKeyPress(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData) { - char text[5]; - if (Emscripten_ConvertUTF32toUTF8(keyEvent->charCode, text)) { - SDL_SendKeyboardText(text); + if (SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE) { + if (SDL_utf8strlen(keyEvent->key) == 1) { + SDL_SendKeyboardText(keyEvent->key); + } } return SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE; }