aboutsummaryrefslogtreecommitdiff
path: root/ui/keymaps.c
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2019-01-22 10:28:14 +0100
committerGerd Hoffmann <kraxel@redhat.com>2019-02-05 10:45:44 +0100
commit19c1b9fd3dd5955893c0d3c187a4180313e9a0f1 (patch)
tree39b304518869487cd9ca826b5c38c9b5fbdb6cff /ui/keymaps.c
parent4ed26e19d90bf5a4ea5662118ae5a2af46e61d36 (diff)
downloadqemu-19c1b9fd3dd5955893c0d3c187a4180313e9a0f1.zip
qemu-19c1b9fd3dd5955893c0d3c187a4180313e9a0f1.tar.gz
qemu-19c1b9fd3dd5955893c0d3c187a4180313e9a0f1.tar.bz2
keymap: fix keyup mappings
It is possible that the modifier state on keyup is different from the modifier state on keydown. In that case the keycode lookup can end up with different keys in case multiple keysym -> keycode mappings exist, because it picks the mapping depending on modifier state. To fix that change the lookup logic for keyup events. Instead of looking at the modifier state check the key state and prefer a keycodes where the key is in "down" state right now. Fixes: abb4f2c965 keymap: consider modifier state when picking a mapping Buglink: https://bugs.launchpad.net/bugs/1738283 Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1658676 Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Message-id: 20190122092814.14919-9-kraxel@redhat.com
Diffstat (limited to 'ui/keymaps.c')
-rw-r--r--ui/keymaps.c55
1 files changed, 34 insertions, 21 deletions
diff --git a/ui/keymaps.c b/ui/keymaps.c
index c8b2135..544b55c 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];