Skip to content

Commit

Permalink
Filter out extended key codes
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Kontrabant committed Jan 10, 2025
1 parent 89e3c65 commit 9abd245
Showing 1 changed file with 53 additions and 5 deletions.
58 changes: 53 additions & 5 deletions src/sdl2_compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1888,18 +1906,48 @@ 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
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;
}
Expand Down

0 comments on commit 9abd245

Please sign in to comment.