瀏覽代碼

The names of keyboards and mice are valid after they've been removed

Fixes https://github.com/libsdl-org/SDL/issues/12816
Sam Lantinga 18 小時之前
父節點
當前提交
00812d13b0
共有 3 個文件被更改,包括 59 次插入46 次删除
  1. 26 19
      src/events/SDL_keyboard.c
  2. 25 19
      src/events/SDL_mouse.c
  3. 8 8
      src/test/SDL_test_common.c

+ 26 - 19
src/events/SDL_keyboard.c

@@ -44,12 +44,6 @@
 #define KEYCODE_OPTION_LATIN_LETTERS    0x04
 #define DEFAULT_KEYCODE_OPTIONS         (KEYCODE_OPTION_FRENCH_NUMBERS | KEYCODE_OPTION_LATIN_LETTERS)
 
-typedef struct SDL_KeyboardInstance
-{
-    SDL_KeyboardID instance_id;
-    char *name;
-} SDL_KeyboardInstance;
-
 typedef struct SDL_Keyboard
 {
     // Data common to all keyboards
@@ -65,7 +59,8 @@ typedef struct SDL_Keyboard
 
 static SDL_Keyboard SDL_keyboard;
 static int SDL_keyboard_count;
-static SDL_KeyboardInstance *SDL_keyboards;
+static SDL_KeyboardID *SDL_keyboards;
+static SDL_HashTable *SDL_keyboard_names;
 static bool SDL_keyboard_quitting;
 
 static void SDLCALL SDL_KeycodeOptionsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
@@ -95,6 +90,9 @@ bool SDL_InitKeyboard(void)
 {
     SDL_AddHintCallback(SDL_HINT_KEYCODE_OPTIONS,
                         SDL_KeycodeOptionsChanged, &SDL_keyboard);
+
+    SDL_keyboard_names = SDL_CreateHashTable(0, true, SDL_HashID, SDL_KeyMatchID, SDL_DestroyHashValue, NULL);
+
     return true;
 }
 
@@ -112,7 +110,7 @@ bool SDL_IsKeyboard(Uint16 vendor, Uint16 product, int num_keys)
 static int SDL_GetKeyboardIndex(SDL_KeyboardID keyboardID)
 {
     for (int i = 0; i < SDL_keyboard_count; ++i) {
-        if (keyboardID == SDL_keyboards[i].instance_id) {
+        if (keyboardID == SDL_keyboards[i]) {
             return i;
         }
     }
@@ -129,16 +127,19 @@ void SDL_AddKeyboard(SDL_KeyboardID keyboardID, const char *name)
 
     SDL_assert(keyboardID != 0);
 
-    SDL_KeyboardInstance *keyboards = (SDL_KeyboardInstance *)SDL_realloc(SDL_keyboards, (SDL_keyboard_count + 1) * sizeof(*keyboards));
+    SDL_KeyboardID *keyboards = (SDL_KeyboardID *)SDL_realloc(SDL_keyboards, (SDL_keyboard_count + 1) * sizeof(*keyboards));
     if (!keyboards) {
         return;
     }
-    SDL_KeyboardInstance *instance = &keyboards[SDL_keyboard_count];
-    instance->instance_id = keyboardID;
-    instance->name = SDL_strdup(name ? name : "");
+    keyboards[SDL_keyboard_count] = keyboardID;
     SDL_keyboards = keyboards;
     ++SDL_keyboard_count;
 
+    if (!name) {
+        name = "Keyboard";
+    }
+    SDL_InsertIntoHashTable(SDL_keyboard_names, (const void *)(uintptr_t)keyboardID, SDL_strdup(name), true);
+
     SDL_Event event;
     SDL_zero(event);
     event.type = SDL_EVENT_KEYBOARD_ADDED;
@@ -154,8 +155,6 @@ void SDL_RemoveKeyboard(SDL_KeyboardID keyboardID)
         return;
     }
 
-    SDL_free(SDL_keyboards[keyboard_index].name);
-
     if (keyboard_index != SDL_keyboard_count - 1) {
         SDL_memmove(&SDL_keyboards[keyboard_index], &SDL_keyboards[keyboard_index + 1], (SDL_keyboard_count - keyboard_index - 1) * sizeof(SDL_keyboards[keyboard_index]));
     }
@@ -187,7 +186,7 @@ SDL_KeyboardID *SDL_GetKeyboards(int *count)
         }
 
         for (i = 0; i < SDL_keyboard_count; ++i) {
-            keyboards[i] = SDL_keyboards[i].instance_id;
+            keyboards[i] = SDL_keyboards[i];
         }
         keyboards[i] = 0;
     } else {
@@ -201,12 +200,17 @@ SDL_KeyboardID *SDL_GetKeyboards(int *count)
 
 const char *SDL_GetKeyboardNameForID(SDL_KeyboardID instance_id)
 {
-    int keyboard_index = SDL_GetKeyboardIndex(instance_id);
-    if (keyboard_index < 0) {
+    const char *name = NULL;
+    if (!SDL_FindInHashTable(SDL_keyboard_names, (const void *)(uintptr_t)instance_id, (const void **)&name)) {
         SDL_SetError("Keyboard %" SDL_PRIu32 " not found", instance_id);
         return NULL;
     }
-    return SDL_GetPersistentString(SDL_keyboards[keyboard_index].name);
+    if (!name) {
+        // SDL_strdup() failed during insert
+        SDL_OutOfMemory();
+        return NULL;
+    }
+    return name;
 }
 
 void SDL_ResetKeyboard(void)
@@ -871,11 +875,14 @@ void SDL_QuitKeyboard(void)
     SDL_keyboard_quitting = true;
 
     for (int i = SDL_keyboard_count; i--;) {
-        SDL_RemoveKeyboard(SDL_keyboards[i].instance_id);
+        SDL_RemoveKeyboard(SDL_keyboards[i]);
     }
     SDL_free(SDL_keyboards);
     SDL_keyboards = NULL;
 
+    SDL_DestroyHashTable(SDL_keyboard_names);
+    SDL_keyboard_names = NULL;
+
     if (SDL_keyboard.keymap && SDL_keyboard.keymap->auto_release) {
         SDL_DestroyKeymap(SDL_keyboard.keymap);
         SDL_keyboard.keymap = NULL;

+ 25 - 19
src/events/SDL_mouse.c

@@ -34,16 +34,11 @@
 
 #define WARP_EMULATION_THRESHOLD_NS SDL_MS_TO_NS(30)
 
-typedef struct SDL_MouseInstance
-{
-    SDL_MouseID instance_id;
-    char *name;
-} SDL_MouseInstance;
-
 // The mouse state
 static SDL_Mouse SDL_mouse;
 static int SDL_mouse_count;
-static SDL_MouseInstance *SDL_mice;
+static SDL_MouseID *SDL_mice;
+static SDL_HashTable *SDL_mouse_names;
 static bool SDL_mouse_quitting;
 
 // for mapping mouse events to touch
@@ -311,6 +306,8 @@ bool SDL_PreInitMouse(void)
 
     mouse->cursor_visible = true;
 
+    SDL_mouse_names = SDL_CreateHashTable(0, true, SDL_HashID, SDL_KeyMatchID, SDL_DestroyHashValue, NULL);
+
     return true;
 }
 
@@ -340,7 +337,7 @@ bool SDL_IsMouse(Uint16 vendor, Uint16 product)
 static int SDL_GetMouseIndex(SDL_MouseID mouseID)
 {
     for (int i = 0; i < SDL_mouse_count; ++i) {
-        if (mouseID == SDL_mice[i].instance_id) {
+        if (mouseID == SDL_mice[i]) {
             return i;
         }
     }
@@ -357,16 +354,19 @@ void SDL_AddMouse(SDL_MouseID mouseID, const char *name)
 
     SDL_assert(mouseID != 0);
 
-    SDL_MouseInstance *mice = (SDL_MouseInstance *)SDL_realloc(SDL_mice, (SDL_mouse_count + 1) * sizeof(*mice));
+    SDL_MouseID *mice = (SDL_MouseID *)SDL_realloc(SDL_mice, (SDL_mouse_count + 1) * sizeof(*mice));
     if (!mice) {
         return;
     }
-    SDL_MouseInstance *instance = &mice[SDL_mouse_count];
-    instance->instance_id = mouseID;
-    instance->name = SDL_strdup(name ? name : "");
+    mice[SDL_mouse_count] = mouseID;
     SDL_mice = mice;
     ++SDL_mouse_count;
 
+    if (!name) {
+        name = "Mouse";
+    }
+    SDL_InsertIntoHashTable(SDL_mouse_names, (const void *)(uintptr_t)mouseID, SDL_strdup(name), true);
+
     SDL_Event event;
     SDL_zero(event);
     event.type = SDL_EVENT_MOUSE_ADDED;
@@ -382,8 +382,6 @@ void SDL_RemoveMouse(SDL_MouseID mouseID)
         return;
     }
 
-    SDL_free(SDL_mice[mouse_index].name);
-
     if (mouse_index != SDL_mouse_count - 1) {
         SDL_memmove(&SDL_mice[mouse_index], &SDL_mice[mouse_index + 1], (SDL_mouse_count - mouse_index - 1) * sizeof(SDL_mice[mouse_index]));
     }
@@ -429,7 +427,7 @@ SDL_MouseID *SDL_GetMice(int *count)
         }
 
         for (i = 0; i < SDL_mouse_count; ++i) {
-            mice[i] = SDL_mice[i].instance_id;
+            mice[i] = SDL_mice[i];
         }
         mice[i] = 0;
     } else {
@@ -443,12 +441,17 @@ SDL_MouseID *SDL_GetMice(int *count)
 
 const char *SDL_GetMouseNameForID(SDL_MouseID instance_id)
 {
-    int mouse_index = SDL_GetMouseIndex(instance_id);
-    if (mouse_index < 0) {
+    const char *name = NULL;
+    if (!SDL_FindInHashTable(SDL_mouse_names, (const void *)(uintptr_t)instance_id, (const void **)&name)) {
         SDL_SetError("Mouse %" SDL_PRIu32 " not found", instance_id);
         return NULL;
     }
-    return SDL_GetPersistentString(SDL_mice[mouse_index].name);
+    if (!name) {
+        // SDL_strdup() failed during insert
+        SDL_OutOfMemory();
+        return NULL;
+    }
+    return name;
 }
 
 void SDL_SetDefaultCursor(SDL_Cursor *cursor)
@@ -1165,11 +1168,14 @@ void SDL_QuitMouse(void)
                         SDL_MouseIntegerModeChanged, mouse);
 
     for (int i = SDL_mouse_count; i--; ) {
-        SDL_RemoveMouse(SDL_mice[i].instance_id);
+        SDL_RemoveMouse(SDL_mice[i]);
     }
     SDL_free(SDL_mice);
     SDL_mice = NULL;
 
+    SDL_DestroyHashTable(SDL_mouse_names);
+    SDL_mouse_names = NULL;
+
     if (mouse->internal) {
         SDL_free(mouse->internal);
         mouse->internal = NULL;

+ 8 - 8
src/test/SDL_test_common.c

@@ -1733,12 +1733,12 @@ void SDLTest_PrintEvent(const SDL_Event *event)
         SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " HDR %s", event->window.windowID, event->window.data1 ? "enabled" : "disabled");
         break;
     case SDL_EVENT_KEYBOARD_ADDED:
-        SDL_Log("SDL EVENT: Keyboard %" SDL_PRIu32 " attached",
-                event->kdevice.which);
+        SDL_Log("SDL EVENT: Keyboard %" SDL_PRIu32 " (%s) attached",
+                event->kdevice.which, SDL_GetKeyboardNameForID(event->kdevice.which));
         break;
     case SDL_EVENT_KEYBOARD_REMOVED:
-        SDL_Log("SDL EVENT: Keyboard %" SDL_PRIu32 " removed",
-                event->kdevice.which);
+        SDL_Log("SDL EVENT: Keyboard %" SDL_PRIu32 " (%s) removed",
+                event->kdevice.which, SDL_GetKeyboardNameForID(event->kdevice.which));
         break;
     case SDL_EVENT_KEY_DOWN:
     case SDL_EVENT_KEY_UP: {
@@ -1775,12 +1775,12 @@ void SDLTest_PrintEvent(const SDL_Event *event)
         SDL_Log("SDL EVENT: Keymap changed");
         break;
     case SDL_EVENT_MOUSE_ADDED:
-        SDL_Log("SDL EVENT: Mouse %" SDL_PRIu32 " attached",
-                event->mdevice.which);
+        SDL_Log("SDL EVENT: Mouse %" SDL_PRIu32 " (%s) attached",
+                event->mdevice.which, SDL_GetMouseNameForID(event->mdevice.which));
         break;
     case SDL_EVENT_MOUSE_REMOVED:
-        SDL_Log("SDL EVENT: Mouse %" SDL_PRIu32 " removed",
-                event->mdevice.which);
+        SDL_Log("SDL EVENT: Mouse %" SDL_PRIu32 " (%s) removed",
+                event->mdevice.which, SDL_GetMouseNameForID(event->mdevice.which));
         break;
     case SDL_EVENT_MOUSE_MOTION:
         SDL_Log("SDL EVENT: Mouse: moved to %g,%g (%g,%g) in window %" SDL_PRIu32,