SDL: wayland: Only clear the key repeat flag when the repeated key is released

From 399cb2f0de2dc840bddba71133a7b54a5ae69ac8 Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
Date: Wed, 21 Sep 2022 13:20:39 -0400
Subject: [PATCH] wayland: Only clear the key repeat flag when the repeated key
 is released

If multiple keys were simultaneously depressed and one was being repeated, the repeat flag was being cleared when any of the pressed keys were released, even if the released key wasn't the one being repeated.

This tracks the key currently being repeated and only clears the repeat flag when the particular key being repeated is released.
---
 src/video/wayland/SDL_waylandevents.c   | 11 ++++++++---
 src/video/wayland/SDL_waylandevents_c.h |  1 +
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index 02c48bccafc..ec2f514eef9 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -233,12 +233,13 @@ keyboard_repeat_clear(SDL_WaylandKeyboardRepeat* repeat_info) {
 }
 
 static void
-keyboard_repeat_set(SDL_WaylandKeyboardRepeat* repeat_info, uint32_t wl_press_time,
+keyboard_repeat_set(SDL_WaylandKeyboardRepeat* repeat_info, uint32_t key, uint32_t wl_press_time,
                     uint32_t scancode, SDL_bool has_text, char text[8]) {
     if (!repeat_info->is_initialized || !repeat_info->repeat_rate) {
         return;
     }
     repeat_info->is_key_down = SDL_TRUE;
+    repeat_info->key = key;
     repeat_info->wl_press_time = wl_press_time;
     repeat_info->sdl_press_time = SDL_GetTicks();
     repeat_info->next_repeat_ms = repeat_info->repeat_delay;
@@ -254,6 +255,10 @@ static SDL_bool keyboard_repeat_is_set(SDL_WaylandKeyboardRepeat* repeat_info) {
     return repeat_info->is_initialized && repeat_info->is_key_down;
 }
 
+static SDL_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;
+}
+
 void
 Wayland_SendWakeupEvent(_THIS, SDL_Window *window)
 {
@@ -1085,7 +1090,7 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
     if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
         has_text = keyboard_input_get_text(text, input, key, SDL_PRESSED, &handled_by_ime);
     } else {
-        if (keyboard_repeat_is_set(&input->keyboard_repeat)) {
+        if (keyboard_repeat_key_is_set(&input->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,
@@ -1114,7 +1119,7 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
             }
         }
         if (input->xkb.keymap && WAYLAND_xkb_keymap_key_repeats(input->xkb.keymap, key + 8)) {
-            keyboard_repeat_set(&input->keyboard_repeat, time, scancode, has_text, text);
+            keyboard_repeat_set(&input->keyboard_repeat, key, time, scancode, has_text, text);
         }
     }
 }
diff --git a/src/video/wayland/SDL_waylandevents_c.h b/src/video/wayland/SDL_waylandevents_c.h
index d70fdee4467..9d240d7bd8d 100644
--- a/src/video/wayland/SDL_waylandevents_c.h
+++ b/src/video/wayland/SDL_waylandevents_c.h
@@ -71,6 +71,7 @@ typedef struct {
     SDL_bool is_initialized;
 
     SDL_bool is_key_down;
+    uint32_t key;
     uint32_t wl_press_time; // Key press time as reported by the Wayland API
     uint32_t sdl_press_time; // Key press time expressed in SDL ticks
     uint32_t next_repeat_ms;