From 9c9bb9cec7e50ccac6e6a75447ca1604ea69ca5e Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
Date: Fri, 11 Jul 2025 11:10:09 -0400
Subject: [PATCH] wayland: Only create/destroy the compose table when necessary
Initializing the compose table is a very expensive operation, and only necessary if the locale envvar changed, which is often not the case when just changing the keymap, so don't destroy and recreate it whenever the keymap changes. The state only needs to be reset in this case.
---
src/video/wayland/SDL_waylandevents.c | 51 ++++++++++++++++---------
src/video/wayland/SDL_waylandevents_c.h | 1 +
2 files changed, 33 insertions(+), 19 deletions(-)
diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index fcf43e6e0fbfc..08288718dd694 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -1495,7 +1495,6 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
{
SDL_WaylandSeat *seat = data;
char *map_str;
- const char *locale;
if (!data) {
close(fd);
@@ -1588,7 +1587,7 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
*/
// Look up the preferred locale, falling back to "C" as default
- locale = SDL_getenv("LC_ALL");
+ const char *locale = SDL_getenv("LC_ALL");
if (!locale) {
locale = SDL_getenv("LC_CTYPE");
if (!locale) {
@@ -1599,26 +1598,38 @@ static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
}
}
- // Set up XKB compose table
- if (seat->keyboard.xkb.compose_table != NULL) {
- WAYLAND_xkb_compose_table_unref(seat->keyboard.xkb.compose_table);
- seat->keyboard.xkb.compose_table = NULL;
- }
- seat->keyboard.xkb.compose_table = WAYLAND_xkb_compose_table_new_from_locale(seat->display->xkb_context,
- locale, XKB_COMPOSE_COMPILE_NO_FLAGS);
- if (seat->keyboard.xkb.compose_table) {
- // Set up XKB compose state
- if (seat->keyboard.xkb.compose_state != NULL) {
- WAYLAND_xkb_compose_state_unref(seat->keyboard.xkb.compose_state);
- seat->keyboard.xkb.compose_state = NULL;
- }
- seat->keyboard.xkb.compose_state = WAYLAND_xkb_compose_state_new(seat->keyboard.xkb.compose_table,
- XKB_COMPOSE_STATE_NO_FLAGS);
- if (!seat->keyboard.xkb.compose_state) {
- SDL_SetError("could not create XKB compose state");
+ /* Set up the XKB compose table.
+ *
+ * This is a very slow operation, so it is only done during initialization,
+ * or if the locale envvar changed during runtime.
+ */
+ if (!seat->keyboard.current_locale || SDL_strcmp(seat->keyboard.current_locale, locale) != 0) {
+ // Cache the current locale for later comparison.
+ SDL_free(seat->keyboard.current_locale);
+ seat->keyboard.current_locale = SDL_strdup(locale);
+
+ if (seat->keyboard.xkb.compose_table != NULL) {
WAYLAND_xkb_compose_table_unref(seat->keyboard.xkb.compose_table);
seat->keyboard.xkb.compose_table = NULL;
}
+ seat->keyboard.xkb.compose_table = WAYLAND_xkb_compose_table_new_from_locale(seat->display->xkb_context,
+ locale, XKB_COMPOSE_COMPILE_NO_FLAGS);
+ if (seat->keyboard.xkb.compose_table) {
+ // Set up XKB compose state
+ if (seat->keyboard.xkb.compose_state != NULL) {
+ WAYLAND_xkb_compose_state_unref(seat->keyboard.xkb.compose_state);
+ seat->keyboard.xkb.compose_state = NULL;
+ }
+ seat->keyboard.xkb.compose_state = WAYLAND_xkb_compose_state_new(seat->keyboard.xkb.compose_table,
+ XKB_COMPOSE_STATE_NO_FLAGS);
+ if (!seat->keyboard.xkb.compose_state) {
+ SDL_SetError("could not create XKB compose state");
+ WAYLAND_xkb_compose_table_unref(seat->keyboard.xkb.compose_table);
+ seat->keyboard.xkb.compose_table = NULL;
+ }
+ }
+ } else if (seat->keyboard.xkb.compose_state) {
+ WAYLAND_xkb_compose_state_reset(seat->keyboard.xkb.compose_state);
}
}
@@ -2216,6 +2227,8 @@ static void Wayland_SeatDestroyKeyboard(SDL_WaylandSeat *seat, bool send_event)
}
}
+ SDL_free(seat->keyboard.current_locale);
+
if (seat->keyboard.xkb.compose_state) {
WAYLAND_xkb_compose_state_unref(seat->keyboard.xkb.compose_state);
}
diff --git a/src/video/wayland/SDL_waylandevents_c.h b/src/video/wayland/SDL_waylandevents_c.h
index 8f27ae978f30b..ffa779e250a5e 100644
--- a/src/video/wayland/SDL_waylandevents_c.h
+++ b/src/video/wayland/SDL_waylandevents_c.h
@@ -76,6 +76,7 @@ typedef struct SDL_WaylandSeat
struct zwp_keyboard_shortcuts_inhibitor_v1 *key_inhibitor;
SDL_WindowData *focus;
SDL_Keymap *sdl_keymap;
+ char *current_locale;
SDL_WaylandKeyboardRepeat repeat;
Uint64 highres_timestamp_ns;