]> git.proxmox.com Git - mirror_qemu.git/blobdiff - ui/keymaps.c
migration/savevm: move non SaveStateEntry condition check out of iteration
[mirror_qemu.git] / ui / keymaps.c
index 43fe604724fe39832c71dd81e6927e85ed93cffd..6e8a321971a2cc49d482a3c9dad6d2465efe746c 100644 (file)
  */
 
 #include "qemu/osdep.h"
+#include "qemu-common.h"
 #include "keymaps.h"
 #include "sysemu/sysemu.h"
 #include "trace.h"
+#include "qemu/ctype.h"
 #include "qemu/error-report.h"
+#include "qapi/error.h"
+#include "ui/input.h"
 
 struct keysym2code {
     uint32_t count;
@@ -79,10 +83,11 @@ static void add_keysym(char *line, int keysym, int keycode, kbd_layout_t *k)
     trace_keymap_add(keysym, keycode, line);
 }
 
-static kbd_layout_t *parse_keyboard_layout(const name2keysym_t *table,
-                                           const char *language,
-                                           kbd_layout_t *k)
+static int parse_keyboard_layout(kbd_layout_t *k,
+                                 const name2keysym_t *table,
+                                 const char *language, Error **errp)
 {
+    int ret;
     FILE *f;
     char * filename;
     char line[1024];
@@ -94,13 +99,8 @@ static kbd_layout_t *parse_keyboard_layout(const name2keysym_t *table,
     f = filename ? fopen(filename, "r") : NULL;
     g_free(filename);
     if (!f) {
-        fprintf(stderr, "Could not read keymap file: '%s'\n", language);
-        return NULL;
-    }
-
-    if (!k) {
-        k = g_new0(kbd_layout_t, 1);
-        k->hash = g_hash_table_new(NULL, NULL);
+        error_setg(errp, "could not read keymap file: '%s'", language);
+        return -1;
     }
 
     for(;;) {
@@ -118,7 +118,9 @@ static kbd_layout_t *parse_keyboard_layout(const name2keysym_t *table,
             continue;
         }
         if (!strncmp(line, "include ", 8)) {
-            parse_keyboard_layout(table, line + 8, k);
+            error_setg(errp, "keymap include files are not supported any more");
+            ret = -1;
+            goto out;
         } else {
             int offset = 0;
             while (line[offset] != 0 &&
@@ -164,20 +166,32 @@ static kbd_layout_t *parse_keyboard_layout(const name2keysym_t *table,
             }
         }
     }
+
+    ret = 0;
+out:
     fclose(f);
-    return k;
+    return ret;
 }
 
 
 kbd_layout_t *init_keyboard_layout(const name2keysym_t *table,
-                                   const char *language)
+                                   const char *language, Error **errp)
 {
-    return parse_keyboard_layout(table, language, NULL);
+    kbd_layout_t *k;
+
+    k = g_new0(kbd_layout_t, 1);
+    k->hash = g_hash_table_new(NULL, NULL);
+    if (parse_keyboard_layout(k, table, language, errp) < 0) {
+        g_hash_table_unref(k->hash);
+        g_free(k);
+        return NULL;
+    }
+    return k;
 }
 
 
 int keysym2scancode(kbd_layout_t *k, int keysym,
-                    bool shift, bool altgr, bool ctrl)
+                    QKbdState *kbd, bool down)
 {
     static const uint32_t mask =
         SCANCODE_SHIFT | SCANCODE_ALTGR | SCANCODE_CTRL;
@@ -201,27 +215,39 @@ int keysym2scancode(kbd_layout_t *k, int keysym,
         return keysym2code->keycodes[0];
     }
 
-    /*
-     * We have multiple keysym -> keycode mappings.
-     *
-     * Check whenever we find one mapping where the modifier state of
-     * the mapping matches the current user interface modifier state.
-     * If so, prefer that one.
-     */
-    mods = 0;
-    if (shift) {
-        mods |= SCANCODE_SHIFT;
-    }
-    if (altgr) {
-        mods |= SCANCODE_ALTGR;
-    }
-    if (ctrl) {
-        mods |= SCANCODE_CTRL;
-    }
+    /* We have multiple keysym -> keycode mappings. */
+    if (down) {
+        /*
+         * On keydown: Check whenever we find one mapping where the
+         * modifier state of the mapping matches the current user
+         * interface modifier state.  If so, prefer that one.
+         */
+        mods = 0;
+        if (kbd && qkbd_state_modifier_get(kbd, QKBD_MOD_SHIFT)) {
+            mods |= SCANCODE_SHIFT;
+        }
+        if (kbd && qkbd_state_modifier_get(kbd, QKBD_MOD_ALTGR)) {
+            mods |= SCANCODE_ALTGR;
+        }
+        if (kbd && qkbd_state_modifier_get(kbd, QKBD_MOD_CTRL)) {
+            mods |= SCANCODE_CTRL;
+        }
 
-    for (i = 0; i < keysym2code->count; i++) {
-        if ((keysym2code->keycodes[i] & mask) == mods) {
-            return keysym2code->keycodes[i];
+        for (i = 0; i < keysym2code->count; i++) {
+            if ((keysym2code->keycodes[i] & mask) == mods) {
+                return keysym2code->keycodes[i];
+            }
+        }
+    } else {
+        /*
+         * On keyup: Try find a key which is actually down.
+         */
+        for (i = 0; i < keysym2code->count; i++) {
+            QKeyCode qcode = qemu_input_key_number_to_qcode
+                (keysym2code->keycodes[i]);
+            if (kbd && qkbd_state_key_get(kbd, qcode)) {
+                return keysym2code->keycodes[i];
+            }
         }
     }
     return keysym2code->keycodes[0];