diff options
Diffstat (limited to 'ui/keymaps.c')
-rw-r--r-- | ui/keymaps.c | 97 |
1 files changed, 61 insertions, 36 deletions
diff --git a/ui/keymaps.c b/ui/keymaps.c index 43fe604724..6ceaa97085 100644 --- a/ui/keymaps.c +++ b/ui/keymaps.c @@ -23,10 +23,13 @@ */ #include "qemu/osdep.h" +#include "qemu/datadir.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 +82,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 +98,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 +117,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 +165,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 +214,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]; |