Skip to content

Commit 00812d1

Browse files
committed
The names of keyboards and mice are valid after they've been removed
Fixes #12816
1 parent 3ddc3f1 commit 00812d1

File tree

3 files changed

+59
-46
lines changed

3 files changed

+59
-46
lines changed

src/events/SDL_keyboard.c

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,6 @@
4444
#define KEYCODE_OPTION_LATIN_LETTERS 0x04
4545
#define DEFAULT_KEYCODE_OPTIONS (KEYCODE_OPTION_FRENCH_NUMBERS | KEYCODE_OPTION_LATIN_LETTERS)
4646

47-
typedef struct SDL_KeyboardInstance
48-
{
49-
SDL_KeyboardID instance_id;
50-
char *name;
51-
} SDL_KeyboardInstance;
52-
5347
typedef struct SDL_Keyboard
5448
{
5549
// Data common to all keyboards
@@ -65,7 +59,8 @@ typedef struct SDL_Keyboard
6559

6660
static SDL_Keyboard SDL_keyboard;
6761
static int SDL_keyboard_count;
68-
static SDL_KeyboardInstance *SDL_keyboards;
62+
static SDL_KeyboardID *SDL_keyboards;
63+
static SDL_HashTable *SDL_keyboard_names;
6964
static bool SDL_keyboard_quitting;
7065

7166
static void SDLCALL SDL_KeycodeOptionsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
@@ -95,6 +90,9 @@ bool SDL_InitKeyboard(void)
9590
{
9691
SDL_AddHintCallback(SDL_HINT_KEYCODE_OPTIONS,
9792
SDL_KeycodeOptionsChanged, &SDL_keyboard);
93+
94+
SDL_keyboard_names = SDL_CreateHashTable(0, true, SDL_HashID, SDL_KeyMatchID, SDL_DestroyHashValue, NULL);
95+
9896
return true;
9997
}
10098

@@ -112,7 +110,7 @@ bool SDL_IsKeyboard(Uint16 vendor, Uint16 product, int num_keys)
112110
static int SDL_GetKeyboardIndex(SDL_KeyboardID keyboardID)
113111
{
114112
for (int i = 0; i < SDL_keyboard_count; ++i) {
115-
if (keyboardID == SDL_keyboards[i].instance_id) {
113+
if (keyboardID == SDL_keyboards[i]) {
116114
return i;
117115
}
118116
}
@@ -129,16 +127,19 @@ void SDL_AddKeyboard(SDL_KeyboardID keyboardID, const char *name)
129127

130128
SDL_assert(keyboardID != 0);
131129

132-
SDL_KeyboardInstance *keyboards = (SDL_KeyboardInstance *)SDL_realloc(SDL_keyboards, (SDL_keyboard_count + 1) * sizeof(*keyboards));
130+
SDL_KeyboardID *keyboards = (SDL_KeyboardID *)SDL_realloc(SDL_keyboards, (SDL_keyboard_count + 1) * sizeof(*keyboards));
133131
if (!keyboards) {
134132
return;
135133
}
136-
SDL_KeyboardInstance *instance = &keyboards[SDL_keyboard_count];
137-
instance->instance_id = keyboardID;
138-
instance->name = SDL_strdup(name ? name : "");
134+
keyboards[SDL_keyboard_count] = keyboardID;
139135
SDL_keyboards = keyboards;
140136
++SDL_keyboard_count;
141137

138+
if (!name) {
139+
name = "Keyboard";
140+
}
141+
SDL_InsertIntoHashTable(SDL_keyboard_names, (const void *)(uintptr_t)keyboardID, SDL_strdup(name), true);
142+
142143
SDL_Event event;
143144
SDL_zero(event);
144145
event.type = SDL_EVENT_KEYBOARD_ADDED;
@@ -154,8 +155,6 @@ void SDL_RemoveKeyboard(SDL_KeyboardID keyboardID)
154155
return;
155156
}
156157

157-
SDL_free(SDL_keyboards[keyboard_index].name);
158-
159158
if (keyboard_index != SDL_keyboard_count - 1) {
160159
SDL_memmove(&SDL_keyboards[keyboard_index], &SDL_keyboards[keyboard_index + 1], (SDL_keyboard_count - keyboard_index - 1) * sizeof(SDL_keyboards[keyboard_index]));
161160
}
@@ -187,7 +186,7 @@ SDL_KeyboardID *SDL_GetKeyboards(int *count)
187186
}
188187

189188
for (i = 0; i < SDL_keyboard_count; ++i) {
190-
keyboards[i] = SDL_keyboards[i].instance_id;
189+
keyboards[i] = SDL_keyboards[i];
191190
}
192191
keyboards[i] = 0;
193192
} else {
@@ -201,12 +200,17 @@ SDL_KeyboardID *SDL_GetKeyboards(int *count)
201200

202201
const char *SDL_GetKeyboardNameForID(SDL_KeyboardID instance_id)
203202
{
204-
int keyboard_index = SDL_GetKeyboardIndex(instance_id);
205-
if (keyboard_index < 0) {
203+
const char *name = NULL;
204+
if (!SDL_FindInHashTable(SDL_keyboard_names, (const void *)(uintptr_t)instance_id, (const void **)&name)) {
206205
SDL_SetError("Keyboard %" SDL_PRIu32 " not found", instance_id);
207206
return NULL;
208207
}
209-
return SDL_GetPersistentString(SDL_keyboards[keyboard_index].name);
208+
if (!name) {
209+
// SDL_strdup() failed during insert
210+
SDL_OutOfMemory();
211+
return NULL;
212+
}
213+
return name;
210214
}
211215

212216
void SDL_ResetKeyboard(void)
@@ -871,11 +875,14 @@ void SDL_QuitKeyboard(void)
871875
SDL_keyboard_quitting = true;
872876

873877
for (int i = SDL_keyboard_count; i--;) {
874-
SDL_RemoveKeyboard(SDL_keyboards[i].instance_id);
878+
SDL_RemoveKeyboard(SDL_keyboards[i]);
875879
}
876880
SDL_free(SDL_keyboards);
877881
SDL_keyboards = NULL;
878882

883+
SDL_DestroyHashTable(SDL_keyboard_names);
884+
SDL_keyboard_names = NULL;
885+
879886
if (SDL_keyboard.keymap && SDL_keyboard.keymap->auto_release) {
880887
SDL_DestroyKeymap(SDL_keyboard.keymap);
881888
SDL_keyboard.keymap = NULL;

src/events/SDL_mouse.c

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,11 @@
3434

3535
#define WARP_EMULATION_THRESHOLD_NS SDL_MS_TO_NS(30)
3636

37-
typedef struct SDL_MouseInstance
38-
{
39-
SDL_MouseID instance_id;
40-
char *name;
41-
} SDL_MouseInstance;
42-
4337
// The mouse state
4438
static SDL_Mouse SDL_mouse;
4539
static int SDL_mouse_count;
46-
static SDL_MouseInstance *SDL_mice;
40+
static SDL_MouseID *SDL_mice;
41+
static SDL_HashTable *SDL_mouse_names;
4742
static bool SDL_mouse_quitting;
4843

4944
// for mapping mouse events to touch
@@ -311,6 +306,8 @@ bool SDL_PreInitMouse(void)
311306

312307
mouse->cursor_visible = true;
313308

309+
SDL_mouse_names = SDL_CreateHashTable(0, true, SDL_HashID, SDL_KeyMatchID, SDL_DestroyHashValue, NULL);
310+
314311
return true;
315312
}
316313

@@ -340,7 +337,7 @@ bool SDL_IsMouse(Uint16 vendor, Uint16 product)
340337
static int SDL_GetMouseIndex(SDL_MouseID mouseID)
341338
{
342339
for (int i = 0; i < SDL_mouse_count; ++i) {
343-
if (mouseID == SDL_mice[i].instance_id) {
340+
if (mouseID == SDL_mice[i]) {
344341
return i;
345342
}
346343
}
@@ -357,16 +354,19 @@ void SDL_AddMouse(SDL_MouseID mouseID, const char *name)
357354

358355
SDL_assert(mouseID != 0);
359356

360-
SDL_MouseInstance *mice = (SDL_MouseInstance *)SDL_realloc(SDL_mice, (SDL_mouse_count + 1) * sizeof(*mice));
357+
SDL_MouseID *mice = (SDL_MouseID *)SDL_realloc(SDL_mice, (SDL_mouse_count + 1) * sizeof(*mice));
361358
if (!mice) {
362359
return;
363360
}
364-
SDL_MouseInstance *instance = &mice[SDL_mouse_count];
365-
instance->instance_id = mouseID;
366-
instance->name = SDL_strdup(name ? name : "");
361+
mice[SDL_mouse_count] = mouseID;
367362
SDL_mice = mice;
368363
++SDL_mouse_count;
369364

365+
if (!name) {
366+
name = "Mouse";
367+
}
368+
SDL_InsertIntoHashTable(SDL_mouse_names, (const void *)(uintptr_t)mouseID, SDL_strdup(name), true);
369+
370370
SDL_Event event;
371371
SDL_zero(event);
372372
event.type = SDL_EVENT_MOUSE_ADDED;
@@ -382,8 +382,6 @@ void SDL_RemoveMouse(SDL_MouseID mouseID)
382382
return;
383383
}
384384

385-
SDL_free(SDL_mice[mouse_index].name);
386-
387385
if (mouse_index != SDL_mouse_count - 1) {
388386
SDL_memmove(&SDL_mice[mouse_index], &SDL_mice[mouse_index + 1], (SDL_mouse_count - mouse_index - 1) * sizeof(SDL_mice[mouse_index]));
389387
}
@@ -429,7 +427,7 @@ SDL_MouseID *SDL_GetMice(int *count)
429427
}
430428

431429
for (i = 0; i < SDL_mouse_count; ++i) {
432-
mice[i] = SDL_mice[i].instance_id;
430+
mice[i] = SDL_mice[i];
433431
}
434432
mice[i] = 0;
435433
} else {
@@ -443,12 +441,17 @@ SDL_MouseID *SDL_GetMice(int *count)
443441

444442
const char *SDL_GetMouseNameForID(SDL_MouseID instance_id)
445443
{
446-
int mouse_index = SDL_GetMouseIndex(instance_id);
447-
if (mouse_index < 0) {
444+
const char *name = NULL;
445+
if (!SDL_FindInHashTable(SDL_mouse_names, (const void *)(uintptr_t)instance_id, (const void **)&name)) {
448446
SDL_SetError("Mouse %" SDL_PRIu32 " not found", instance_id);
449447
return NULL;
450448
}
451-
return SDL_GetPersistentString(SDL_mice[mouse_index].name);
449+
if (!name) {
450+
// SDL_strdup() failed during insert
451+
SDL_OutOfMemory();
452+
return NULL;
453+
}
454+
return name;
452455
}
453456

454457
void SDL_SetDefaultCursor(SDL_Cursor *cursor)
@@ -1165,11 +1168,14 @@ void SDL_QuitMouse(void)
11651168
SDL_MouseIntegerModeChanged, mouse);
11661169

11671170
for (int i = SDL_mouse_count; i--; ) {
1168-
SDL_RemoveMouse(SDL_mice[i].instance_id);
1171+
SDL_RemoveMouse(SDL_mice[i]);
11691172
}
11701173
SDL_free(SDL_mice);
11711174
SDL_mice = NULL;
11721175

1176+
SDL_DestroyHashTable(SDL_mouse_names);
1177+
SDL_mouse_names = NULL;
1178+
11731179
if (mouse->internal) {
11741180
SDL_free(mouse->internal);
11751181
mouse->internal = NULL;

src/test/SDL_test_common.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1733,12 +1733,12 @@ void SDLTest_PrintEvent(const SDL_Event *event)
17331733
SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " HDR %s", event->window.windowID, event->window.data1 ? "enabled" : "disabled");
17341734
break;
17351735
case SDL_EVENT_KEYBOARD_ADDED:
1736-
SDL_Log("SDL EVENT: Keyboard %" SDL_PRIu32 " attached",
1737-
event->kdevice.which);
1736+
SDL_Log("SDL EVENT: Keyboard %" SDL_PRIu32 " (%s) attached",
1737+
event->kdevice.which, SDL_GetKeyboardNameForID(event->kdevice.which));
17381738
break;
17391739
case SDL_EVENT_KEYBOARD_REMOVED:
1740-
SDL_Log("SDL EVENT: Keyboard %" SDL_PRIu32 " removed",
1741-
event->kdevice.which);
1740+
SDL_Log("SDL EVENT: Keyboard %" SDL_PRIu32 " (%s) removed",
1741+
event->kdevice.which, SDL_GetKeyboardNameForID(event->kdevice.which));
17421742
break;
17431743
case SDL_EVENT_KEY_DOWN:
17441744
case SDL_EVENT_KEY_UP: {
@@ -1775,12 +1775,12 @@ void SDLTest_PrintEvent(const SDL_Event *event)
17751775
SDL_Log("SDL EVENT: Keymap changed");
17761776
break;
17771777
case SDL_EVENT_MOUSE_ADDED:
1778-
SDL_Log("SDL EVENT: Mouse %" SDL_PRIu32 " attached",
1779-
event->mdevice.which);
1778+
SDL_Log("SDL EVENT: Mouse %" SDL_PRIu32 " (%s) attached",
1779+
event->mdevice.which, SDL_GetMouseNameForID(event->mdevice.which));
17801780
break;
17811781
case SDL_EVENT_MOUSE_REMOVED:
1782-
SDL_Log("SDL EVENT: Mouse %" SDL_PRIu32 " removed",
1783-
event->mdevice.which);
1782+
SDL_Log("SDL EVENT: Mouse %" SDL_PRIu32 " (%s) removed",
1783+
event->mdevice.which, SDL_GetMouseNameForID(event->mdevice.which));
17841784
break;
17851785
case SDL_EVENT_MOUSE_MOTION:
17861786
SDL_Log("SDL EVENT: Mouse: moved to %g,%g (%g,%g) in window %" SDL_PRIu32,

0 commit comments

Comments
 (0)