mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-28 14:08:28 +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 KEYCODE_OPTION_LATIN_LETTERS 0x04
|
||||||
#define DEFAULT_KEYCODE_OPTIONS (KEYCODE_OPTION_FRENCH_NUMBERS | KEYCODE_OPTION_LATIN_LETTERS)
|
#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
|
typedef struct SDL_Keyboard
|
||||||
{
|
{
|
||||||
// Data common to all keyboards
|
// Data common to all keyboards
|
||||||
@@ -65,7 +59,8 @@ typedef struct SDL_Keyboard
|
|||||||
|
|
||||||
static SDL_Keyboard SDL_keyboard;
|
static SDL_Keyboard SDL_keyboard;
|
||||||
static int SDL_keyboard_count;
|
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 bool SDL_keyboard_quitting;
|
||||||
|
|
||||||
static void SDLCALL SDL_KeycodeOptionsChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
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_AddHintCallback(SDL_HINT_KEYCODE_OPTIONS,
|
||||||
SDL_KeycodeOptionsChanged, &SDL_keyboard);
|
SDL_KeycodeOptionsChanged, &SDL_keyboard);
|
||||||
|
|
||||||
|
SDL_keyboard_names = SDL_CreateHashTable(0, true, SDL_HashID, SDL_KeyMatchID, SDL_DestroyHashValue, NULL);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +110,7 @@ bool SDL_IsKeyboard(Uint16 vendor, Uint16 product, int num_keys)
|
|||||||
static int SDL_GetKeyboardIndex(SDL_KeyboardID keyboardID)
|
static int SDL_GetKeyboardIndex(SDL_KeyboardID keyboardID)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < SDL_keyboard_count; ++i) {
|
for (int i = 0; i < SDL_keyboard_count; ++i) {
|
||||||
if (keyboardID == SDL_keyboards[i].instance_id) {
|
if (keyboardID == SDL_keyboards[i]) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -129,16 +127,19 @@ void SDL_AddKeyboard(SDL_KeyboardID keyboardID, const char *name)
|
|||||||
|
|
||||||
SDL_assert(keyboardID != 0);
|
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) {
|
if (!keyboards) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SDL_KeyboardInstance *instance = &keyboards[SDL_keyboard_count];
|
keyboards[SDL_keyboard_count] = keyboardID;
|
||||||
instance->instance_id = keyboardID;
|
|
||||||
instance->name = SDL_strdup(name ? name : "");
|
|
||||||
SDL_keyboards = keyboards;
|
SDL_keyboards = keyboards;
|
||||||
++SDL_keyboard_count;
|
++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_Event event;
|
||||||
SDL_zero(event);
|
SDL_zero(event);
|
||||||
event.type = SDL_EVENT_KEYBOARD_ADDED;
|
event.type = SDL_EVENT_KEYBOARD_ADDED;
|
||||||
@@ -154,8 +155,6 @@ void SDL_RemoveKeyboard(SDL_KeyboardID keyboardID)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_free(SDL_keyboards[keyboard_index].name);
|
|
||||||
|
|
||||||
if (keyboard_index != SDL_keyboard_count - 1) {
|
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]));
|
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) {
|
for (i = 0; i < SDL_keyboard_count; ++i) {
|
||||||
keyboards[i] = SDL_keyboards[i].instance_id;
|
keyboards[i] = SDL_keyboards[i];
|
||||||
}
|
}
|
||||||
keyboards[i] = 0;
|
keyboards[i] = 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -201,12 +200,17 @@ SDL_KeyboardID *SDL_GetKeyboards(int *count)
|
|||||||
|
|
||||||
const char *SDL_GetKeyboardNameForID(SDL_KeyboardID instance_id)
|
const char *SDL_GetKeyboardNameForID(SDL_KeyboardID instance_id)
|
||||||
{
|
{
|
||||||
int keyboard_index = SDL_GetKeyboardIndex(instance_id);
|
const char *name = NULL;
|
||||||
if (keyboard_index < 0) {
|
if (!SDL_FindInHashTable(SDL_keyboard_names, (const void *)(uintptr_t)instance_id, (const void **)&name)) {
|
||||||
SDL_SetError("Keyboard %" SDL_PRIu32 " not found", instance_id);
|
SDL_SetError("Keyboard %" SDL_PRIu32 " not found", instance_id);
|
||||||
return NULL;
|
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)
|
void SDL_ResetKeyboard(void)
|
||||||
@@ -871,11 +875,14 @@ void SDL_QuitKeyboard(void)
|
|||||||
SDL_keyboard_quitting = true;
|
SDL_keyboard_quitting = true;
|
||||||
|
|
||||||
for (int i = SDL_keyboard_count; i--;) {
|
for (int i = SDL_keyboard_count; i--;) {
|
||||||
SDL_RemoveKeyboard(SDL_keyboards[i].instance_id);
|
SDL_RemoveKeyboard(SDL_keyboards[i]);
|
||||||
}
|
}
|
||||||
SDL_free(SDL_keyboards);
|
SDL_free(SDL_keyboards);
|
||||||
SDL_keyboards = NULL;
|
SDL_keyboards = NULL;
|
||||||
|
|
||||||
|
SDL_DestroyHashTable(SDL_keyboard_names);
|
||||||
|
SDL_keyboard_names = NULL;
|
||||||
|
|
||||||
if (SDL_keyboard.keymap && SDL_keyboard.keymap->auto_release) {
|
if (SDL_keyboard.keymap && SDL_keyboard.keymap->auto_release) {
|
||||||
SDL_DestroyKeymap(SDL_keyboard.keymap);
|
SDL_DestroyKeymap(SDL_keyboard.keymap);
|
||||||
SDL_keyboard.keymap = NULL;
|
SDL_keyboard.keymap = NULL;
|
||||||
|
@@ -34,16 +34,11 @@
|
|||||||
|
|
||||||
#define WARP_EMULATION_THRESHOLD_NS SDL_MS_TO_NS(30)
|
#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
|
// The mouse state
|
||||||
static SDL_Mouse SDL_mouse;
|
static SDL_Mouse SDL_mouse;
|
||||||
static int SDL_mouse_count;
|
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;
|
static bool SDL_mouse_quitting;
|
||||||
|
|
||||||
// for mapping mouse events to touch
|
// for mapping mouse events to touch
|
||||||
@@ -311,6 +306,8 @@ bool SDL_PreInitMouse(void)
|
|||||||
|
|
||||||
mouse->cursor_visible = true;
|
mouse->cursor_visible = true;
|
||||||
|
|
||||||
|
SDL_mouse_names = SDL_CreateHashTable(0, true, SDL_HashID, SDL_KeyMatchID, SDL_DestroyHashValue, NULL);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,7 +337,7 @@ bool SDL_IsMouse(Uint16 vendor, Uint16 product)
|
|||||||
static int SDL_GetMouseIndex(SDL_MouseID mouseID)
|
static int SDL_GetMouseIndex(SDL_MouseID mouseID)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < SDL_mouse_count; ++i) {
|
for (int i = 0; i < SDL_mouse_count; ++i) {
|
||||||
if (mouseID == SDL_mice[i].instance_id) {
|
if (mouseID == SDL_mice[i]) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -357,16 +354,19 @@ void SDL_AddMouse(SDL_MouseID mouseID, const char *name)
|
|||||||
|
|
||||||
SDL_assert(mouseID != 0);
|
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) {
|
if (!mice) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SDL_MouseInstance *instance = &mice[SDL_mouse_count];
|
mice[SDL_mouse_count] = mouseID;
|
||||||
instance->instance_id = mouseID;
|
|
||||||
instance->name = SDL_strdup(name ? name : "");
|
|
||||||
SDL_mice = mice;
|
SDL_mice = mice;
|
||||||
++SDL_mouse_count;
|
++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_Event event;
|
||||||
SDL_zero(event);
|
SDL_zero(event);
|
||||||
event.type = SDL_EVENT_MOUSE_ADDED;
|
event.type = SDL_EVENT_MOUSE_ADDED;
|
||||||
@@ -382,8 +382,6 @@ void SDL_RemoveMouse(SDL_MouseID mouseID)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_free(SDL_mice[mouse_index].name);
|
|
||||||
|
|
||||||
if (mouse_index != SDL_mouse_count - 1) {
|
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]));
|
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) {
|
for (i = 0; i < SDL_mouse_count; ++i) {
|
||||||
mice[i] = SDL_mice[i].instance_id;
|
mice[i] = SDL_mice[i];
|
||||||
}
|
}
|
||||||
mice[i] = 0;
|
mice[i] = 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -443,12 +441,17 @@ SDL_MouseID *SDL_GetMice(int *count)
|
|||||||
|
|
||||||
const char *SDL_GetMouseNameForID(SDL_MouseID instance_id)
|
const char *SDL_GetMouseNameForID(SDL_MouseID instance_id)
|
||||||
{
|
{
|
||||||
int mouse_index = SDL_GetMouseIndex(instance_id);
|
const char *name = NULL;
|
||||||
if (mouse_index < 0) {
|
if (!SDL_FindInHashTable(SDL_mouse_names, (const void *)(uintptr_t)instance_id, (const void **)&name)) {
|
||||||
SDL_SetError("Mouse %" SDL_PRIu32 " not found", instance_id);
|
SDL_SetError("Mouse %" SDL_PRIu32 " not found", instance_id);
|
||||||
return NULL;
|
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)
|
void SDL_SetDefaultCursor(SDL_Cursor *cursor)
|
||||||
@@ -1165,11 +1168,14 @@ void SDL_QuitMouse(void)
|
|||||||
SDL_MouseIntegerModeChanged, mouse);
|
SDL_MouseIntegerModeChanged, mouse);
|
||||||
|
|
||||||
for (int i = SDL_mouse_count; i--; ) {
|
for (int i = SDL_mouse_count; i--; ) {
|
||||||
SDL_RemoveMouse(SDL_mice[i].instance_id);
|
SDL_RemoveMouse(SDL_mice[i]);
|
||||||
}
|
}
|
||||||
SDL_free(SDL_mice);
|
SDL_free(SDL_mice);
|
||||||
SDL_mice = NULL;
|
SDL_mice = NULL;
|
||||||
|
|
||||||
|
SDL_DestroyHashTable(SDL_mouse_names);
|
||||||
|
SDL_mouse_names = NULL;
|
||||||
|
|
||||||
if (mouse->internal) {
|
if (mouse->internal) {
|
||||||
SDL_free(mouse->internal);
|
SDL_free(mouse->internal);
|
||||||
mouse->internal = NULL;
|
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");
|
SDL_Log("SDL EVENT: Window %" SDL_PRIu32 " HDR %s", event->window.windowID, event->window.data1 ? "enabled" : "disabled");
|
||||||
break;
|
break;
|
||||||
case SDL_EVENT_KEYBOARD_ADDED:
|
case SDL_EVENT_KEYBOARD_ADDED:
|
||||||
SDL_Log("SDL EVENT: Keyboard %" SDL_PRIu32 " attached",
|
SDL_Log("SDL EVENT: Keyboard %" SDL_PRIu32 " (%s) attached",
|
||||||
event->kdevice.which);
|
event->kdevice.which, SDL_GetKeyboardNameForID(event->kdevice.which));
|
||||||
break;
|
break;
|
||||||
case SDL_EVENT_KEYBOARD_REMOVED:
|
case SDL_EVENT_KEYBOARD_REMOVED:
|
||||||
SDL_Log("SDL EVENT: Keyboard %" SDL_PRIu32 " removed",
|
SDL_Log("SDL EVENT: Keyboard %" SDL_PRIu32 " (%s) removed",
|
||||||
event->kdevice.which);
|
event->kdevice.which, SDL_GetKeyboardNameForID(event->kdevice.which));
|
||||||
break;
|
break;
|
||||||
case SDL_EVENT_KEY_DOWN:
|
case SDL_EVENT_KEY_DOWN:
|
||||||
case SDL_EVENT_KEY_UP: {
|
case SDL_EVENT_KEY_UP: {
|
||||||
@@ -1775,12 +1775,12 @@ void SDLTest_PrintEvent(const SDL_Event *event)
|
|||||||
SDL_Log("SDL EVENT: Keymap changed");
|
SDL_Log("SDL EVENT: Keymap changed");
|
||||||
break;
|
break;
|
||||||
case SDL_EVENT_MOUSE_ADDED:
|
case SDL_EVENT_MOUSE_ADDED:
|
||||||
SDL_Log("SDL EVENT: Mouse %" SDL_PRIu32 " attached",
|
SDL_Log("SDL EVENT: Mouse %" SDL_PRIu32 " (%s) attached",
|
||||||
event->mdevice.which);
|
event->mdevice.which, SDL_GetMouseNameForID(event->mdevice.which));
|
||||||
break;
|
break;
|
||||||
case SDL_EVENT_MOUSE_REMOVED:
|
case SDL_EVENT_MOUSE_REMOVED:
|
||||||
SDL_Log("SDL EVENT: Mouse %" SDL_PRIu32 " removed",
|
SDL_Log("SDL EVENT: Mouse %" SDL_PRIu32 " (%s) removed",
|
||||||
event->mdevice.which);
|
event->mdevice.which, SDL_GetMouseNameForID(event->mdevice.which));
|
||||||
break;
|
break;
|
||||||
case SDL_EVENT_MOUSE_MOTION:
|
case SDL_EVENT_MOUSE_MOTION:
|
||||||
SDL_Log("SDL EVENT: Mouse: moved to %g,%g (%g,%g) in window %" SDL_PRIu32,
|
SDL_Log("SDL EVENT: Mouse: moved to %g,%g (%g,%g) in window %" SDL_PRIu32,
|
||||||
|
Reference in New Issue
Block a user