Initial support for hotplugging mice and keyboards

This commit is contained in:
Sam Lantinga 2024-03-20 06:58:00 -07:00
parent c33e4c998d
commit 2fe1a6a279
44 changed files with 961 additions and 321 deletions

View file

@ -55,6 +55,8 @@ struct SDL_Keyboard
};
static SDL_Keyboard SDL_keyboard;
static int SDL_keyboard_count;
static SDL_KeyboardID *SDL_keyboards;
static const SDL_Keycode SDL_default_keymap[SDL_NUM_SCANCODES] = {
/* 0 */ SDLK_UNKNOWN,
@ -678,6 +680,109 @@ int SDL_InitKeyboard(void)
return 0;
}
SDL_bool SDL_IsKeyboard(Uint16 vendor, Uint16 product, int num_keys)
{
const int REAL_KEYBOARD_KEY_COUNT = 50;
if (num_keys > 0 && num_keys < REAL_KEYBOARD_KEY_COUNT) {
return SDL_FALSE;
}
/* Eventually we'll have a blacklist of devices that enumerate as keyboards but aren't really */
return SDL_TRUE;
}
void SDL_PrivateKeyboardAdded(SDL_KeyboardID keyboardID)
{
int keyboard_index = -1;
SDL_assert(keyboardID != 0);
for (int i = 0; i < SDL_keyboard_count; ++i) {
if (keyboardID == SDL_keyboards[i]) {
keyboard_index = i;
break;
}
}
if (keyboard_index >= 0) {
/* We already know about this keyboard */
return;
}
SDL_KeyboardID *keyboards = (SDL_KeyboardID *)SDL_realloc(SDL_keyboards, (SDL_keyboard_count + 1) * sizeof(*keyboards));
if (!keyboards) {
return;
}
keyboards[SDL_keyboard_count] = keyboardID;
SDL_keyboards = keyboards;
++SDL_keyboard_count;
SDL_Event event;
SDL_zero(event);
event.type = SDL_EVENT_KEYBOARD_ADDED;
event.kdevice.which = keyboardID;
SDL_PushEvent(&event);
}
void SDL_PrivateKeyboardRemoved(SDL_KeyboardID keyboardID)
{
int keyboard_index = -1;
SDL_assert(keyboardID != 0);
for (int i = 0; i < SDL_keyboard_count; ++i) {
if (keyboardID == SDL_keyboards[i]) {
keyboard_index = i;
break;
}
}
if (keyboard_index < 0) {
/* We don't know about this keyboard */
return;
}
if (keyboard_index != SDL_keyboard_count - 1) {
SDL_memcpy(&SDL_keyboards[keyboard_index], &SDL_keyboards[keyboard_index + 1], (SDL_keyboard_count - keyboard_index - 1) * sizeof(SDL_keyboards[keyboard_index]));
}
--SDL_keyboard_count;
SDL_Event event;
SDL_zero(event);
event.type = SDL_EVENT_KEYBOARD_REMOVED;
event.kdevice.which = keyboardID;
SDL_PushEvent(&event);
}
SDL_bool SDL_HasKeyboard(void)
{
return (SDL_keyboard_count > 0);
}
SDL_KeyboardID *SDL_GetKeyboards(int *count)
{
int i;
SDL_KeyboardID *keyboards;
keyboards = (SDL_JoystickID *)SDL_malloc((SDL_keyboard_count + 1) * sizeof(*keyboards));
if (keyboards) {
if (count) {
*count = SDL_keyboard_count;
}
for (i = 0; i < SDL_keyboard_count; ++i) {
keyboards[i] = SDL_keyboards[i];
}
keyboards[i] = 0;
} else {
if (count) {
*count = 0;
}
}
return keyboards;
}
void SDL_ResetKeyboard(void)
{
SDL_Keyboard *keyboard = &SDL_keyboard;
@ -688,7 +793,7 @@ void SDL_ResetKeyboard(void)
#endif
for (scancode = (SDL_Scancode)0; scancode < SDL_NUM_SCANCODES; ++scancode) {
if (keyboard->keystate[scancode] == SDL_PRESSED) {
SDL_SendKeyboardKey(0, SDL_RELEASED, scancode);
SDL_SendKeyboardKey(0, 0, SDL_RELEASED, scancode);
}
}
}
@ -822,7 +927,7 @@ int SDL_SetKeyboardFocus(SDL_Window *window)
return 0;
}
static int SDL_SendKeyboardKeyInternal(Uint64 timestamp, Uint32 flags, Uint8 state, SDL_Scancode scancode, SDL_Keycode keycode)
static int SDL_SendKeyboardKeyInternal(Uint64 timestamp, Uint32 flags, SDL_KeyboardID keyboardID, Uint8 state, SDL_Scancode scancode, SDL_Keycode keycode)
{
SDL_Keyboard *keyboard = &SDL_keyboard;
int posted;
@ -831,6 +936,13 @@ static int SDL_SendKeyboardKeyInternal(Uint64 timestamp, Uint32 flags, Uint8 sta
Uint8 repeat = SDL_FALSE;
const Uint8 source = flags & KEYBOARD_SOURCE_MASK;
if (keyboardID == 0) {
if (source == KEYBOARD_HARDWARE && SDL_keyboard_count > 0) {
/* Assume it's from the first keyboard */
keyboardID = SDL_keyboards[0];
}
}
if (scancode == SDL_SCANCODE_UNKNOWN || scancode >= SDL_NUM_SCANCODES) {
return 0;
}
@ -949,6 +1061,7 @@ static int SDL_SendKeyboardKeyInternal(Uint64 timestamp, Uint32 flags, Uint8 sta
event.key.keysym.sym = keycode;
event.key.keysym.mod = keyboard->modstate;
event.key.windowID = keyboard->focus ? keyboard->focus->id : 0;
event.key.which = keyboardID;
posted = (SDL_PushEvent(&event) > 0);
}
@ -982,43 +1095,43 @@ int SDL_SendKeyboardUnicodeKey(Uint64 timestamp, Uint32 ch)
if (mod & SDL_KMOD_SHIFT) {
/* If the character uses shift, press shift down */
SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_PRESSED, SDL_SCANCODE_LSHIFT, SDLK_UNKNOWN);
SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, 0, SDL_PRESSED, SDL_SCANCODE_LSHIFT, SDLK_UNKNOWN);
}
/* Send a keydown and keyup for the character */
SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_PRESSED, code, SDLK_UNKNOWN);
SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_RELEASED, code, SDLK_UNKNOWN);
SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, 0, SDL_PRESSED, code, SDLK_UNKNOWN);
SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, 0, SDL_RELEASED, code, SDLK_UNKNOWN);
if (mod & SDL_KMOD_SHIFT) {
/* If the character uses shift, release shift */
SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, SDL_RELEASED, SDL_SCANCODE_LSHIFT, SDLK_UNKNOWN);
SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, 0, SDL_RELEASED, SDL_SCANCODE_LSHIFT, SDLK_UNKNOWN);
}
return 0;
}
int SDL_SendVirtualKeyboardKey(Uint64 timestamp, Uint8 state, SDL_Scancode scancode)
{
return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, state, scancode, SDLK_UNKNOWN);
return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_VIRTUAL, 0, state, scancode, SDLK_UNKNOWN);
}
int SDL_SendKeyboardKey(Uint64 timestamp, Uint8 state, SDL_Scancode scancode)
int SDL_SendKeyboardKey(Uint64 timestamp, SDL_KeyboardID keyboardID, Uint8 state, SDL_Scancode scancode)
{
return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE, state, scancode, SDLK_UNKNOWN);
return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE, keyboardID, state, scancode, SDLK_UNKNOWN);
}
int SDL_SendKeyboardKeyAndKeycode(Uint64 timestamp, Uint8 state, SDL_Scancode scancode, SDL_Keycode keycode)
int SDL_SendKeyboardKeyAndKeycode(Uint64 timestamp, SDL_KeyboardID keyboardID, Uint8 state, SDL_Scancode scancode, SDL_Keycode keycode)
{
return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE, state, scancode, keycode);
return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE, keyboardID, state, scancode, keycode);
}
int SDL_SendKeyboardKeyAutoRelease(Uint64 timestamp, SDL_Scancode scancode)
{
return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_AUTORELEASE, SDL_PRESSED, scancode, SDLK_UNKNOWN);
return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_AUTORELEASE, 0, SDL_PRESSED, scancode, SDLK_UNKNOWN);
}
int SDL_SendKeyboardKeyIgnoreModifiers(Uint64 timestamp, Uint8 state, SDL_Scancode scancode)
int SDL_SendKeyboardKeyIgnoreModifiers(Uint64 timestamp, SDL_KeyboardID keyboardID, Uint8 state, SDL_Scancode scancode)
{
return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE | KEYBOARD_IGNOREMODIFIERS, state, scancode, SDLK_UNKNOWN);
return SDL_SendKeyboardKeyInternal(timestamp, KEYBOARD_HARDWARE | KEYBOARD_IGNOREMODIFIERS, keyboardID, state, scancode, SDLK_UNKNOWN);
}
void SDL_ReleaseAutoReleaseKeys(void)
@ -1029,7 +1142,7 @@ void SDL_ReleaseAutoReleaseKeys(void)
if (keyboard->autorelease_pending) {
for (scancode = SDL_SCANCODE_UNKNOWN; scancode < SDL_NUM_SCANCODES; ++scancode) {
if (keyboard->keysource[scancode] == KEYBOARD_AUTORELEASE) {
SDL_SendKeyboardKeyInternal(0, KEYBOARD_AUTORELEASE, SDL_RELEASED, scancode, SDLK_UNKNOWN);
SDL_SendKeyboardKeyInternal(0, KEYBOARD_AUTORELEASE, 0, SDL_RELEASED, scancode, SDLK_UNKNOWN);
}
}
keyboard->autorelease_pending = SDL_FALSE;
@ -1117,6 +1230,9 @@ int SDL_SendEditingText(const char *text, int start, int length)
void SDL_QuitKeyboard(void)
{
SDL_keyboard_count = 0;
SDL_free(SDL_keyboards);
SDL_keyboards = NULL;
}
const Uint8 *SDL_GetKeyboardState(int *numkeys)