From 9abd2456d028453d5745b9571839b97a68617f45 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Fri, 10 Jan 2025 11:55:20 -0500 Subject: [PATCH] Filter out extended key codes SDL2 has no mapping for extended keycodes, and SDL2 apps/games are likely not expecting them. If an extended key code is encountered, the key will be derived from the scancode, and the standard scancode will be returned for unmapped keys. --- src/sdl2_compat.c | 58 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/src/sdl2_compat.c b/src/sdl2_compat.c index 0b24a55..7b461fe 100644 --- a/src/sdl2_compat.c +++ b/src/sdl2_compat.c @@ -1277,6 +1277,24 @@ static SDL2_Scancode SDL3ScancodeToSDL2Scancode(SDL_Scancode scancode) } } +static SDL_Keycode SDL3KeycodeToSDL2Keycode(SDL_Scancode scancode, SDL_Keycode keycode) +{ + /* Keys without the extended mask are passed through. */ + if (!(keycode & SDLK_EXTENDED_MASK)) { + return keycode; + } + + /* SDLK_TAB is an ASCII value and can't be converted directly from a scancode. */ + if (keycode == SDLK_LEFT_TAB) { + return SDLK_TAB; + } + + /* Convert the scancode directly to the keycode. This matches the mapping behavior + * of SDL2 backends unless some very esoteric key remapping is being used. + */ + return SDL_SCANCODE_TO_KEYCODE(scancode); +} + /* (current) strategy for SDL_Events: in sdl12-compat, we built our own event queue, so when the SDL2 queue is pumped, we took the events we cared about and added them to the sdl12-compat queue, and otherwise @@ -1318,7 +1336,7 @@ Event3to2(const SDL_Event *event3, SDL2_Event *event2) case SDL_EVENT_KEY_DOWN: case SDL_EVENT_KEY_UP: event2->key.keysym.scancode = SDL3ScancodeToSDL2Scancode(event3->key.scancode); - event2->key.keysym.sym = event3->key.key; + event2->key.keysym.sym = SDL3KeycodeToSDL2Keycode(event3->key.scancode, event3->key.key); event2->key.keysym.mod = event3->key.mod; event2->key.state = event3->key.down; event2->key.repeat = event3->key.repeat; @@ -1888,11 +1906,14 @@ SDL_GetKeyFromScancode(SDL2_Scancode scancode) } if (scancode <= SDL2_SCANCODE_MODE) { - // They're the same - return SDL3_GetKeyFromScancode(SDL2ScancodeToSDL3Scancode(scancode), SDL_KMOD_NONE, true); - } else { - return SDL_SCANCODE_TO_KEYCODE(scancode); + /* Filter out extended keycodes. This matches the key mapping behavior of SDL2 backends. */ + const SDL_Keycode keycode = SDL3_GetKeyFromScancode(SDL2ScancodeToSDL3Scancode(scancode), SDL_KMOD_NONE, true); + if (!(keycode & SDLK_EXTENDED_MASK)) { + return keycode; + } } + + return SDL_SCANCODE_TO_KEYCODE(scancode); } SDL_DECLSPEC SDL2_Scancode SDLCALL @@ -1900,6 +1921,33 @@ SDL_GetScancodeFromKey(SDL_Keycode key) { SDL_Keymod modstate = SDL_KMOD_NONE; SDL_Scancode scancode = SDL3_GetScancodeFromKey(key, &modstate); + + if (scancode == SDL_SCANCODE_UNKNOWN) { + /* Keys commonly remapped to extended keycodes in SDL3. + * If the keymap returns no mapping, convert the key to a scancode directly. + */ + switch (key) { + case SDLK_LCTRL: + case SDLK_RCTRL: + case SDLK_LALT: + case SDLK_RALT: + case SDLK_LGUI: + case SDLK_RGUI: + case SDLK_CAPSLOCK: + case SDLK_SCROLLLOCK: + case SDLK_PRINTSCREEN: + case SDLK_INSERT: + scancode = (SDL_Scancode)(key & ~SDLK_SCANCODE_MASK); + break; + case SDLK_TAB: + /* ASCII value that can't be directly converted to a scancode. */ + scancode = SDL_SCANCODE_TAB; + break; + default: + break; + } + } + if (modstate != SDL_KMOD_NONE) { return SDL2_SCANCODE_UNKNOWN; }