소스 검색

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.
Frank Praznik 2 주 전
부모
커밋
9c9bb9cec7
2개의 변경된 파일33개의 추가작업 그리고 19개의 파일을 삭제
  1. 32 19
      src/video/wayland/SDL_waylandevents.c
  2. 1 0
      src/video/wayland/SDL_waylandevents_c.h

+ 32 - 19
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);
     }

+ 1 - 0
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;