mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-28 05:58:29 +00:00
The names of keyboards and mice are valid after they've been removed
Fixes https://github.com/libsdl-org/SDL/issues/12816
This commit is contained in:
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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,
|
||||
|
Reference in New Issue
Block a user