Browse Source

Fixed key names for non-latin keyboard layouts

Sam Lantinga 8 tháng trước cách đây
mục cha
commit
4f7c0e7c46
2 tập tin đã thay đổi với 44 bổ sung36 xóa
  1. 35 17
      src/events/SDL_keyboard.c
  2. 9 19
      src/events/SDL_keymap.c

+ 35 - 17
src/events/SDL_keyboard.c

@@ -57,7 +57,8 @@ typedef struct SDL_Keyboard
     Uint8 keystate[SDL_NUM_SCANCODES];
     SDL_Keymap *keymap;
     SDL_bool french_numbers;
-    SDL_bool non_latin_letters;
+    SDL_bool latin_letters;
+    SDL_bool thai_keyboard;
     Uint32 keycode_options;
     SDL_bool autorelease_pending;
     Uint64 hardware_timestamp;
@@ -229,6 +230,17 @@ SDL_Keymap *SDL_GetCurrentKeymap(void)
 {
     SDL_Keyboard *keyboard = &SDL_keyboard;
 
+    if (keyboard->thai_keyboard) {
+        // Thai keyboards are QWERTY plus Thai characters, use the default QWERTY keymap
+        return NULL;
+    }
+
+    if ((keyboard->keycode_options & KEYCODE_OPTION_LATIN_LETTERS) &&
+        !keyboard->latin_letters) {
+        // We'll use the default QWERTY keymap
+        return NULL;
+    }
+
     return keyboard->keymap;
 }
 
@@ -253,10 +265,17 @@ void SDL_SetKeymap(SDL_Keymap *keymap, SDL_bool send_event)
     }
 
     // Detect non-Latin keymap
-    keyboard->non_latin_letters = SDL_TRUE;
+    keyboard->thai_keyboard = SDL_FALSE;
+    keyboard->latin_letters = SDL_FALSE;
     for (int i = SDL_SCANCODE_A; i <= SDL_SCANCODE_D; ++i) {
-        if (SDL_GetKeymapKeycode(keymap, (SDL_Scancode)i, SDL_KMOD_NONE) <= 0xFF) {
-            keyboard->non_latin_letters = SDL_FALSE;
+        SDL_Keycode key = SDL_GetKeymapKeycode(keymap, (SDL_Scancode)i, SDL_KMOD_NONE);
+        if (key <= 0xFF) {
+            keyboard->latin_letters = SDL_TRUE;
+            break;
+        }
+
+        if (key >= 0x0E00 && key <= 0x0E7F) {
+            keyboard->thai_keyboard = SDL_TRUE;
             break;
         }
     }
@@ -437,30 +456,29 @@ SDL_Keycode SDL_GetKeyFromScancode(SDL_Scancode scancode, SDL_Keymod modstate, S
     SDL_Keycode keycode;
 
     if (key_event) {
+        SDL_Keymap *keymap = SDL_GetCurrentKeymap();
         SDL_bool numlock = (modstate & SDL_KMOD_NUM) != 0;
 
         // We won't be applying any modifiers by default
         modstate = SDL_KMOD_NONE;
 
-        if ((keyboard->keycode_options & KEYCODE_OPTION_LATIN_LETTERS) &&
-            keyboard->non_latin_letters) {
-            keycode = SDL_GetKeymapKeycode(NULL, scancode, modstate);
-        } else {
-            if ((keyboard->keycode_options & KEYCODE_OPTION_FRENCH_NUMBERS) &&
-                keyboard->french_numbers &&
-                (scancode >= SDL_SCANCODE_1 && scancode <= SDL_SCANCODE_0)) {
-                // Add the shift state to generate a numeric keycode
-                modstate |= SDL_KMOD_SHIFT;
-            }
-
-            keycode = SDL_GetKeymapKeycode(keyboard->keymap, scancode, modstate);
+        if ((keyboard->keycode_options & KEYCODE_OPTION_FRENCH_NUMBERS) &&
+            keyboard->french_numbers &&
+            (scancode >= SDL_SCANCODE_1 && scancode <= SDL_SCANCODE_0)) {
+            // Add the shift state to generate a numeric keycode
+            modstate |= SDL_KMOD_SHIFT;
         }
 
+        keycode = SDL_GetKeymapKeycode(keymap, scancode, modstate);
+
         if (keyboard->keycode_options & KEYCODE_OPTION_HIDE_NUMPAD) {
             keycode = SDL_ConvertNumpadKeycode(keycode, numlock);
         }
     } else {
-        keycode = SDL_GetKeymapKeycode(keyboard->keymap, scancode, modstate);
+        // Use the real keymap
+        SDL_Keymap *keymap = keyboard->keymap;
+
+        keycode = SDL_GetKeymapKeycode(keymap, scancode, modstate);
     }
     return keycode;
 }

+ 9 - 19
src/events/SDL_keymap.c

@@ -1008,17 +1008,11 @@ const char *SDL_GetKeyName(SDL_Keycode key, SDL_bool uppercase)
             // SDL_Keycode is defined as the unshifted key on the keyboard,
             // but the key name is defined as the letter printed on that key,
             // which is usually the shifted capital letter.
-            if (key >= 'a' && key <= 'z') {
-                key = 'A' + (key - 'a');
-            } else if (key > 0x7F) {
+            if (key > 0x7F || (key >= 'a' && key <= 'z')) {
                 SDL_Keymap *keymap = SDL_GetCurrentKeymap();
-                SDL_Scancode scancode = SDL_GetKeymapScancode(keymap, key, NULL);
-                if (scancode != SDL_SCANCODE_UNKNOWN) {
-                    if (key >= 0x0E00 && key <= 0x0E7F) {
-                        // Thai keyboards are QWERTY plus Thai characters, so let's use the ASCII key names
-                        return SDL_GetScancodeName(scancode);
-                    }
-
+                SDL_Keymod modstate;
+                SDL_Scancode scancode = SDL_GetKeymapScancode(keymap, key, &modstate);
+                if (scancode != SDL_SCANCODE_UNKNOWN && !(modstate & SDL_KMOD_SHIFT)) {
                     SDL_Keycode capital = SDL_GetKeymapKeycode(keymap, scancode, SDL_KMOD_SHIFT);
                     if (capital > 0x7F || (capital >= 'A' && capital <= 'Z')) {
                         key = capital;
@@ -1083,15 +1077,11 @@ SDL_Keycode SDL_GetKeyFromName(const char *name, SDL_bool uppercase)
             // SDL_Keycode is defined as the unshifted key on the keyboard,
             // but the key name is defined as the letter printed on that key,
             // which is usually the shifted capital letter.
-            if (key >= 'A' && key <= 'Z') {
-                key = 'a' + (key - 'A');
-            } else if (key > 0x7F) {
-                SDL_Keymap *keymap = SDL_GetCurrentKeymap();
-                SDL_Keymod modstate;
-                SDL_Scancode scancode = SDL_GetKeymapScancode(keymap, key, &modstate);
-                if (scancode != SDL_SCANCODE_UNKNOWN && (modstate & SDL_KMOD_SHIFT)) {
-                    key = SDL_GetKeymapKeycode(keymap, scancode, SDL_KMOD_NONE);
-                }
+            SDL_Keymap *keymap = SDL_GetCurrentKeymap();
+            SDL_Keymod modstate;
+            SDL_Scancode scancode = SDL_GetKeymapScancode(keymap, key, &modstate);
+            if (scancode != SDL_SCANCODE_UNKNOWN && (modstate & SDL_KMOD_SHIFT)) {
+                key = SDL_GetKeymapKeycode(keymap, scancode, SDL_KMOD_NONE);
             }
         }
         return key;