From 16f8122a0d481825cfd77dea02ec75d3e02ddce4 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Fri, 31 Jan 2025 12:07:08 -0800
Subject: [PATCH] Keep the simplest mapping of scancode + modifer for a given
keycode
Fixes https://github.com/libsdl-org/sdl2-compat/issues/259
---
src/events/SDL_keymap.c | 32 ++++++++++++++++++++++++--------
1 file changed, 24 insertions(+), 8 deletions(-)
diff --git a/src/events/SDL_keymap.c b/src/events/SDL_keymap.c
index 5c3f784c6c7b8..bc21c33103476 100644
--- a/src/events/SDL_keymap.c
+++ b/src/events/SDL_keymap.c
@@ -72,20 +72,36 @@ void SDL_SetKeymapEntry(SDL_Keymap *keymap, SDL_Scancode scancode, SDL_Keymod mo
return;
}
- if (keycode == SDL_GetKeymapKeycode(keymap, scancode, modstate)) {
- return;
- }
-
- Uint32 key = ((Uint32)NormalizeModifierStateForKeymap(modstate) << 16) | scancode;
+ modstate = NormalizeModifierStateForKeymap(modstate);
+ Uint32 key = ((Uint32)modstate << 16) | scancode;
const void *value;
if (SDL_FindInHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, &value)) {
+ SDL_Keycode existing_keycode = (SDL_Keycode)(uintptr_t)value;
+ if (existing_keycode == keycode) {
+ // We already have this mapping
+ return;
+ }
+
// Changing the mapping, need to remove the existing entry from the keymap
SDL_RemoveFromHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key);
- SDL_RemoveFromHashTable(keymap->keycode_to_scancode, value);
}
-
SDL_InsertIntoHashTable(keymap->scancode_to_keycode, (void *)(uintptr_t)key, (void *)(uintptr_t)keycode);
- SDL_InsertIntoHashTable(keymap->keycode_to_scancode, (void *)(uintptr_t)keycode, (void *)(uintptr_t)key);
+
+ bool update_keycode = true;
+ if (SDL_FindInHashTable(keymap->keycode_to_scancode, (void *)(uintptr_t)keycode, &value)) {
+ Uint32 existing_value = (Uint32)(uintptr_t)value;
+ SDL_Keymod existing_modstate = (SDL_Keymod)(existing_value >> 16);
+
+ // Keep the simplest combination of scancode and modifiers to generate this keycode
+ if (existing_modstate <= modstate) {
+ update_keycode = false;
+ } else {
+ SDL_RemoveFromHashTable(keymap->keycode_to_scancode, (void *)(uintptr_t)keycode);
+ }
+ }
+ if (update_keycode) {
+ SDL_InsertIntoHashTable(keymap->keycode_to_scancode, (void *)(uintptr_t)keycode, (void *)(uintptr_t)key);
+ }
}
SDL_Keycode SDL_GetKeymapKeycode(SDL_Keymap *keymap, SDL_Scancode scancode, SDL_Keymod modstate)