Commit c3d1037665c1b058d3c1f99d7aa0372145a938dd

Sam Lantinga 2014-03-23T09:44:04

Better keyboard detection when some of the keys are remapped, thanks to Lewis Wall

diff --git a/src/video/x11/SDL_x11keyboard.c b/src/video/x11/SDL_x11keyboard.c
index 3603460..5014b71 100644
--- a/src/video/x11/SDL_x11keyboard.c
+++ b/src/video/x11/SDL_x11keyboard.c
@@ -207,14 +207,20 @@ X11_InitKeyboard(_THIS)
     } fingerprint[] = {
         { SDL_SCANCODE_HOME, XK_Home, 0 },
         { SDL_SCANCODE_PAGEUP, XK_Prior, 0 },
-        { SDL_SCANCODE_PAGEDOWN, XK_Next, 0 },
+        { SDL_SCANCODE_UP, XK_Up, 0 },
+        { SDL_SCANCODE_LEFT, XK_Left, 0 },
+        { SDL_SCANCODE_DELETE, XK_Delete, 0 },
+        { SDL_SCANCODE_KP_ENTER, XK_KP_Enter, 0 },
     };
-    SDL_bool fingerprint_detected;
+    int best_distance;
+    int best_index;
+    int distance;
 
     X11_XAutoRepeatOn(data->display);
 
     /* Try to determine which scancodes are being used based on fingerprint */
-    fingerprint_detected = SDL_FALSE;
+    best_distance = SDL_arraysize(fingerprint) + 1;
+    best_index = -1;
     X11_XDisplayKeycodes(data->display, &min_keycode, &max_keycode);
     for (i = 0; i < SDL_arraysize(fingerprint); ++i) {
         fingerprint[i].value =
@@ -226,28 +232,28 @@ X11_InitKeyboard(_THIS)
         if ((max_keycode - min_keycode + 1) <= scancode_set[i].table_size) {
             continue;
         }
+        distance = 0;
         for (j = 0; j < SDL_arraysize(fingerprint); ++j) {
             if (fingerprint[j].value < 0
                 || fingerprint[j].value >= scancode_set[i].table_size) {
-                break;
-            }
-            if (scancode_set[i].table[fingerprint[j].value] !=
-                fingerprint[j].scancode) {
-                break;
+                distance += 1;
+            } else if (scancode_set[i].table[fingerprint[j].value] != fingerprint[j].scancode) {
+                distance += 1;
             }
         }
-        if (j == SDL_arraysize(fingerprint)) {
+        if (distance < best_distance) {
+            best_distance = distance;
+            best_index = i;
+        }
+    }
+    if (best_index >= 0 && best_distance <= 2) {
 #ifdef DEBUG_KEYBOARD
-            printf("Using scancode set %d, min_keycode = %d, max_keycode = %d, table_size = %d\n", i, min_keycode, max_keycode, scancode_set[i].table_size);
+        printf("Using scancode set %d, min_keycode = %d, max_keycode = %d, table_size = %d\n", best_index, min_keycode, max_keycode, scancode_set[best_index].table_size);
 #endif
-            SDL_memcpy(&data->key_layout[min_keycode], scancode_set[i].table,
-                       sizeof(SDL_Scancode) * scancode_set[i].table_size);
-            fingerprint_detected = SDL_TRUE;
-            break;
-        }
+        SDL_memcpy(&data->key_layout[min_keycode], scancode_set[best_index].table,
+                   sizeof(SDL_Scancode) * scancode_set[best_index].table_size);
     }
-
-    if (!fingerprint_detected) {
+    else {
         SDL_Keycode keymap[SDL_NUM_SCANCODES];
 
         printf