mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-27 02:46:08 +08:00
Fix lost KEY_UP events with multiple keyboards using shared scancode state (#14446)
This commit is contained in:
@@ -51,6 +51,7 @@ typedef struct SDL_Keyboard
|
|||||||
SDL_Keymod modstate;
|
SDL_Keymod modstate;
|
||||||
Uint8 keysource[SDL_SCANCODE_COUNT];
|
Uint8 keysource[SDL_SCANCODE_COUNT];
|
||||||
bool keystate[SDL_SCANCODE_COUNT];
|
bool keystate[SDL_SCANCODE_COUNT];
|
||||||
|
Uint8 keyrefcount[SDL_SCANCODE_COUNT]; // how many devices hold this key
|
||||||
SDL_Keymap *keymap;
|
SDL_Keymap *keymap;
|
||||||
Uint32 keycode_options;
|
Uint32 keycode_options;
|
||||||
bool autorelease_pending;
|
bool autorelease_pending;
|
||||||
@@ -88,6 +89,10 @@ static void SDLCALL SDL_KeycodeOptionsChanged(void *userdata, const char *name,
|
|||||||
// Public functions
|
// Public functions
|
||||||
bool SDL_InitKeyboard(void)
|
bool SDL_InitKeyboard(void)
|
||||||
{
|
{
|
||||||
|
// Init key reference counts to 0
|
||||||
|
SDL_Keyboard *keyboard = &SDL_keyboard;
|
||||||
|
SDL_zeroa(keyboard->keyrefcount);
|
||||||
|
|
||||||
SDL_AddHintCallback(SDL_HINT_KEYCODE_OPTIONS,
|
SDL_AddHintCallback(SDL_HINT_KEYCODE_OPTIONS,
|
||||||
SDL_KeycodeOptionsChanged, &SDL_keyboard);
|
SDL_KeycodeOptionsChanged, &SDL_keyboard);
|
||||||
|
|
||||||
@@ -225,6 +230,7 @@ void SDL_ResetKeyboard(void)
|
|||||||
if (keyboard->keystate[scancode]) {
|
if (keyboard->keystate[scancode]) {
|
||||||
SDL_SendKeyboardKey(0, SDL_GLOBAL_KEYBOARD_ID, 0, (SDL_Scancode)scancode, false);
|
SDL_SendKeyboardKey(0, SDL_GLOBAL_KEYBOARD_ID, 0, (SDL_Scancode)scancode, false);
|
||||||
}
|
}
|
||||||
|
keyboard->keyrefcount[scancode] = 0; // Reset reference count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -522,6 +528,7 @@ static bool SDL_SendKeyboardKeyInternal(Uint64 timestamp, Uint32 flags, SDL_Keyb
|
|||||||
SDL_Keycode keycode = SDLK_UNKNOWN;
|
SDL_Keycode keycode = SDLK_UNKNOWN;
|
||||||
Uint32 type;
|
Uint32 type;
|
||||||
bool repeat = false;
|
bool repeat = false;
|
||||||
|
bool last_release = false;
|
||||||
const Uint8 source = flags & KEYBOARD_SOURCE_MASK;
|
const Uint8 source = flags & KEYBOARD_SOURCE_MASK;
|
||||||
|
|
||||||
#ifdef DEBUG_KEYBOARD
|
#ifdef DEBUG_KEYBOARD
|
||||||
@@ -538,6 +545,9 @@ static bool SDL_SendKeyboardKeyInternal(Uint64 timestamp, Uint32 flags, SDL_Keyb
|
|||||||
if (scancode > SDL_SCANCODE_UNKNOWN && scancode < SDL_SCANCODE_COUNT) {
|
if (scancode > SDL_SCANCODE_UNKNOWN && scancode < SDL_SCANCODE_COUNT) {
|
||||||
// Drop events that don't change state
|
// Drop events that don't change state
|
||||||
if (down) {
|
if (down) {
|
||||||
|
if (keyboard->keyrefcount[scancode] < 255) {
|
||||||
|
keyboard->keyrefcount[scancode]++;
|
||||||
|
}
|
||||||
if (keyboard->keystate[scancode]) {
|
if (keyboard->keystate[scancode]) {
|
||||||
if (!(keyboard->keysource[scancode] & source)) {
|
if (!(keyboard->keysource[scancode] & source)) {
|
||||||
keyboard->keysource[scancode] |= source;
|
keyboard->keysource[scancode] |= source;
|
||||||
@@ -547,14 +557,22 @@ static bool SDL_SendKeyboardKeyInternal(Uint64 timestamp, Uint32 flags, SDL_Keyb
|
|||||||
}
|
}
|
||||||
keyboard->keysource[scancode] |= source;
|
keyboard->keysource[scancode] |= source;
|
||||||
} else {
|
} else {
|
||||||
if (!keyboard->keystate[scancode]) {
|
if (keyboard->keyrefcount[scancode] == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
keyboard->keysource[scancode] = 0;
|
--keyboard->keyrefcount[scancode];
|
||||||
|
if (keyboard->keyrefcount[scancode] == 0) {
|
||||||
|
keyboard->keysource[scancode] = 0;
|
||||||
|
last_release = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update internal keyboard state
|
// Update internal keyboard state
|
||||||
keyboard->keystate[scancode] = down;
|
if (down) {
|
||||||
|
keyboard->keystate[scancode] = true;
|
||||||
|
} else if (last_release) {
|
||||||
|
keyboard->keystate[scancode] = false;
|
||||||
|
}
|
||||||
|
|
||||||
keycode = SDL_GetKeyFromScancode(scancode, keyboard->modstate, true);
|
keycode = SDL_GetKeyFromScancode(scancode, keyboard->modstate, true);
|
||||||
|
|
||||||
@@ -621,7 +639,9 @@ static bool SDL_SendKeyboardKeyInternal(Uint64 timestamp, Uint32 flags, SDL_Keyb
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
keyboard->modstate &= ~modifier;
|
if (last_release) {
|
||||||
|
keyboard->modstate &= ~modifier;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user