|
|
@@ -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 = {
|