summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ui/curses.c2
-rw-r--r--ui/keymaps.c55
-rw-r--r--ui/keymaps.h2
-rw-r--r--ui/vnc.c2
4 files changed, 37 insertions, 24 deletions
diff --git a/ui/curses.c b/ui/curses.c
index 54687589d4..6e0091c3b2 100644
--- a/ui/curses.c
+++ b/ui/curses.c
@@ -273,7 +273,7 @@ static void curses_refresh(DisplayChangeListener *dcl)
}
keycode = keysym2scancode(kbd_layout, keysym & KEYSYM_MASK,
- NULL);
+ NULL, false);
if (keycode == 0)
continue;
diff --git a/ui/keymaps.c b/ui/keymaps.c
index c8b2135340..544b55c27b 100644
--- a/ui/keymaps.c
+++ b/ui/keymaps.c
@@ -28,6 +28,7 @@
#include "trace.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
+#include "ui/input.h"
struct keysym2code {
uint32_t count;
@@ -188,7 +189,7 @@ kbd_layout_t *init_keyboard_layout(const name2keysym_t *table,
int keysym2scancode(kbd_layout_t *k, int keysym,
- QKbdState *kbd)
+ QKbdState *kbd, bool down)
{
static const uint32_t mask =
SCANCODE_SHIFT | SCANCODE_ALTGR | SCANCODE_CTRL;
@@ -212,27 +213,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 (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;
- }
+ /* 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];
diff --git a/ui/keymaps.h b/ui/keymaps.h
index d8652b8a5a..b6d48aac40 100644
--- a/ui/keymaps.h
+++ b/ui/keymaps.h
@@ -56,7 +56,7 @@ typedef struct kbd_layout_t kbd_layout_t;
kbd_layout_t *init_keyboard_layout(const name2keysym_t *table,
const char *language, Error **errp);
int keysym2scancode(kbd_layout_t *k, int keysym,
- QKbdState *kbd);
+ QKbdState *kbd, bool down);
int keycode_is_keypad(kbd_layout_t *k, int keycode);
int keysym_is_numlock(kbd_layout_t *k, int keysym);
diff --git a/ui/vnc.c b/ui/vnc.c
index f66ed53094..0fef646fc4 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1981,7 +1981,7 @@ static void key_event(VncState *vs, int down, uint32_t sym)
}
keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF,
- vs->vd->kbd) & SCANCODE_KEYMASK;
+ vs->vd->kbd, down) & SCANCODE_KEYMASK;
trace_vnc_key_event_map(down, sym, keycode, code2name(keycode));
do_key_event(vs, down, keycode, sym);
}