diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index cc3469a222..56e6b61b94 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -411,11 +411,9 @@ static void Wayland_SeatSetKeymap(SDL_WaylandSeat *seat) } } -// Returns true if a key repeat event was due -static bool keyboard_repeat_handle(SDL_WaylandKeyboardRepeat *repeat_info, Uint64 elapsed) +// Synthesize key repeat events +static void keyboard_repeat_handle(SDL_WaylandKeyboardRepeat *repeat_info, Uint64 elapsed) { - bool ret = false; - while (elapsed >= repeat_info->next_repeat_ns) { if (repeat_info->scancode != SDL_SCANCODE_UNKNOWN) { const Uint64 timestamp = repeat_info->base_time_ns + repeat_info->next_repeat_ns; @@ -425,26 +423,15 @@ static bool keyboard_repeat_handle(SDL_WaylandKeyboardRepeat *repeat_info, Uint6 SDL_SendKeyboardText(repeat_info->text); } repeat_info->next_repeat_ns += SDL_NS_PER_SECOND / (Uint64)repeat_info->repeat_rate; - ret = true; } - return ret; -} - -static void keyboard_repeat_clear(SDL_WaylandKeyboardRepeat *repeat_info) -{ - if (!repeat_info->is_initialized) { - return; - } - repeat_info->is_key_down = false; } static void keyboard_repeat_set(SDL_WaylandKeyboardRepeat *repeat_info, Uint32 keyboard_id, uint32_t key, Uint32 wl_press_time_ms, - Uint64 base_time_ns, uint32_t scancode, bool has_text, char text[8]) + Uint64 base_time_ns, uint32_t scancode, const char *text) { - if (!repeat_info->is_initialized || !repeat_info->repeat_rate) { + if (!repeat_info->repeat_rate) { return; } - repeat_info->is_key_down = true; repeat_info->keyboard_id = keyboard_id; repeat_info->key = key; repeat_info->wl_press_time_ms = wl_press_time_ms; @@ -452,39 +439,13 @@ static void keyboard_repeat_set(SDL_WaylandKeyboardRepeat *repeat_info, Uint32 k repeat_info->sdl_press_time_ns = SDL_GetTicksNS(); repeat_info->next_repeat_ns = SDL_MS_TO_NS(repeat_info->repeat_delay_ms); repeat_info->scancode = scancode; - if (has_text) { - SDL_memcpy(repeat_info->text, text, sizeof(repeat_info->text)); + if (text) { + SDL_strlcpy(repeat_info->text, text, SDL_arraysize(repeat_info->text)); } else { repeat_info->text[0] = '\0'; } } -static uint32_t keyboard_repeat_get_key(SDL_WaylandKeyboardRepeat *repeat_info) -{ - if (repeat_info->is_initialized && repeat_info->is_key_down) { - return repeat_info->key; - } - - return 0; -} - -static void keyboard_repeat_set_text(SDL_WaylandKeyboardRepeat *repeat_info, const char text[8]) -{ - if (repeat_info->is_initialized) { - SDL_copyp(repeat_info->text, text); - } -} - -static bool keyboard_repeat_is_set(SDL_WaylandKeyboardRepeat *repeat_info) -{ - return repeat_info->is_initialized && repeat_info->is_key_down; -} - -static bool keyboard_repeat_key_is_set(SDL_WaylandKeyboardRepeat *repeat_info, uint32_t key) -{ - return repeat_info->is_initialized && repeat_info->is_key_down && key == repeat_info->key; -} - static void sync_done_handler(void *data, struct wl_callback *callback, uint32_t callback_data) { // Nothing to do, just destroy the callback @@ -527,7 +488,7 @@ int Wayland_WaitEventTimeout(SDL_VideoDevice *_this, Sint64 timeoutNS) // If key repeat is active, we'll need to cap our maximum wait time to handle repeats wl_list_for_each (seat, &d->seat_list, link) { - if (keyboard_repeat_is_set(&seat->keyboard.repeat)) { + if (seat->keyboard.repeat.key) { const Uint64 elapsed = start - seat->keyboard.repeat.sdl_press_time_ns; const Uint64 next_repeat_wait_time = (seat->keyboard.repeat.next_repeat_ns - elapsed) + 1; if (timeoutNS < 0 || next_repeat_wait_time <= timeoutNS) { @@ -664,7 +625,7 @@ void Wayland_PumpEvents(SDL_VideoDevice *_this) if (ret >= 0) { // Synthesize key repeat events. wl_list_for_each (seat, &d->seat_list, link) { - if (keyboard_repeat_is_set(&seat->keyboard.repeat)) { + if (seat->keyboard.repeat.key) { Wayland_SeatSetKeymap(seat); const Uint64 elapsed = SDL_GetTicksNS() - seat->keyboard.repeat.sdl_press_time_ns; @@ -2181,7 +2142,7 @@ static void keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, } // Stop key repeat before clearing keyboard focus - keyboard_repeat_clear(&seat->keyboard.repeat); + seat->keyboard.repeat.key = 0; SDL_Window *keyboard_focus = SDL_GetKeyboardFocus(); @@ -2304,7 +2265,7 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard, has_text = keyboard_input_get_text(text, seat, key, true, &handled_by_ime); } } else { - if (keyboard_repeat_key_is_set(&seat->keyboard.repeat, key)) { + if (key == seat->keyboard.repeat.key) { /* Send any due key repeat events before stopping the repeat and generating the key up event. * Compute time based on the Wayland time, as it reports when the release event happened. * Using SDL_GetTicks would be wrong, as it would report when the release event is processed, @@ -2312,7 +2273,7 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard, */ const Uint64 elapsed = SDL_MS_TO_NS(time - seat->keyboard.repeat.wl_press_time_ms); keyboard_repeat_handle(&seat->keyboard.repeat, elapsed); - keyboard_repeat_clear(&seat->keyboard.repeat); + seat->keyboard.repeat.key = 0; } keyboard_input_get_text(text, seat, key, false, &handled_by_ime); } @@ -2348,7 +2309,7 @@ static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard, SDL_SendKeyboardText(text); } if (seat->keyboard.xkb.keymap && WAYLAND_xkb_keymap_key_repeats(seat->keyboard.xkb.keymap, key + 8)) { - keyboard_repeat_set(&seat->keyboard.repeat, seat->keyboard.sdl_id, key, time, timestamp_ns, scancode, has_text, text); + keyboard_repeat_set(&seat->keyboard.repeat, seat->keyboard.sdl_id, key, time, timestamp_ns, scancode, has_text ? text : NULL); } } } @@ -2378,12 +2339,11 @@ static void keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, 0, 0, group); // If a key is repeating, update the text to apply the modifier. - if (keyboard_repeat_is_set(&seat->keyboard.repeat)) { + if (seat->keyboard.repeat.key) { char text[8]; - const uint32_t key = keyboard_repeat_get_key(&seat->keyboard.repeat); - if (keyboard_input_get_text(text, seat, key, true, NULL)) { - keyboard_repeat_set_text(&seat->keyboard.repeat, text); + if (keyboard_input_get_text(text, seat, seat->keyboard.repeat.key, true, NULL)) { + SDL_strlcpy(seat->keyboard.repeat.text, text, SDL_arraysize(seat->keyboard.repeat.text)); } } @@ -2401,9 +2361,12 @@ static void keyboard_handle_repeat_info(void *data, struct wl_keyboard *wl_keybo int32_t rate, int32_t delay) { SDL_WaylandSeat *seat = data; - seat->keyboard.repeat.repeat_rate = SDL_clamp(rate, 0, 1000); + seat->keyboard.repeat.repeat_rate = rate; seat->keyboard.repeat.repeat_delay_ms = delay; - seat->keyboard.repeat.is_initialized = true; + + if (!rate) { + seat->keyboard.repeat.key = 0; // Cancel the repeat to avoid dividing by a rate of zero. + } } static const struct wl_keyboard_listener keyboard_listener = { diff --git a/src/video/wayland/SDL_waylandevents_c.h b/src/video/wayland/SDL_waylandevents_c.h index 9e3d573b6c..42faffd7fa 100644 --- a/src/video/wayland/SDL_waylandevents_c.h +++ b/src/video/wayland/SDL_waylandevents_c.h @@ -43,16 +43,14 @@ typedef struct { Sint32 repeat_rate; // Repeat rate in range of [1, 1000] character(s) per second Sint32 repeat_delay_ms; // Time to first repeat event in milliseconds - Uint32 keyboard_id; // ID of the source keyboard. - bool is_initialized; - bool is_key_down; - Uint32 key; + Uint32 key; // Key code of the repeating key + Uint32 scancode; // Scancode of the repeating key + Uint32 keyboard_id; // ID of the source keyboard Uint32 wl_press_time_ms; // Key press time as reported by the Wayland API in milliseconds Uint64 base_time_ns; // Key press time as reported by the Wayland API in nanoseconds Uint64 sdl_press_time_ns; // Key press time expressed in SDL ticks Uint64 next_repeat_ns; // Next repeat event in nanoseconds - Uint32 scancode; char text[8]; } SDL_WaylandKeyboardRepeat;