]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
ui/input: Use Linux key codes for internal key events
authorAkihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Wed, 20 May 2026 06:47:47 +0000 (15:47 +0900)
committerMarc-André Lureau <marcandre.lureau@redhat.com>
Sun, 24 May 2026 21:00:54 +0000 (01:00 +0400)
Linux input key codes are a better internal representation than
QKeyCode:

- With Linux input key codes as the internal representation, keys
  previously lost solely because the middle layer between event sources
  and sinks used QKeyCode will be preserved, since Linux key codes
  cover all keys that those sources and sinks use. For example,
  KEY_KPJPCOMMA cannot be represented with QKeyCode, but it is widely
  supported by event sources and sinks since it is included in linux,
  atset1, atset2, usb, x11, osx, qnum (derived from atset1),
  xorgxquartz, and xorgevdev (derived from linux).

- They make it possible to pass through Linux host key codes to Linux
  guests to preserve all key inputs.

- They simplify consumers by avoiding QKeyCode aliases, namely
  asterisk/kp_multiply and sysrq/print.

This matches the approach used by virtio and Xen.

Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-ID: <20260520-input-v3-4-7c9e4c7abe34@rsg.ci.i.u-tokyo.ac.jp>

16 files changed:
hw/arm/musicpal.c
hw/char/escc.c
hw/display/xenfb.c
hw/input/adb-kbd.c
hw/input/hid.c
hw/input/ps2.c
hw/input/stellaris_gamepad.c
hw/input/virtio-input-hid.c
hw/m68k/next-kbd.c
include/ui/input.h
replay/replay-input.c
tools/qemu-vnc/input.c
tools/qemu-vnc/trace-events
ui/input-keymap.c
ui/input.c
ui/meson.build

index f436bd13d912e3bfaece5ab6d794b2703af40f93..c8985a58f9935c89c2ae29a40803e2cd8c60fe23 100644 (file)
@@ -1069,7 +1069,7 @@ static void musicpal_key_event(DeviceState *dev, QemuConsole *src,
                                QemuInputEvent *evt)
 {
     musicpal_key_state *s = MUSICPAL_KEY(dev);
-    int qcode = evt->key.key;
+    int qcode = qemu_input_linux_to_qcode(evt->key.key);
     uint32_t event = 0;
     int i;
 
index 3ad803537e5e5d86a9de60c105b77b9d8ab79887..39483ca03bf29da409d30f8db8d7c2fe798a0d03 100644 (file)
@@ -800,7 +800,7 @@ static void sunkbd_handle_event(DeviceState *dev, QemuConsole *src,
     int qcode, keycode;
 
     assert(evt->type == INPUT_EVENT_KIND_KEY);
-    qcode = evt->key.key;
+    qcode = qemu_input_linux_to_qcode(evt->key.key);
     trace_escc_sunkbd_event_in(qcode, QKeyCode_str(qcode),
                                evt->key.down);
 
index 176796cbf62fb7a5c7f8b300b727cd72738a6dde..218f37f07400e6f6a52f618a2af36052f83fa6e0 100644 (file)
@@ -203,7 +203,7 @@ static void xenfb_key_event(DeviceState *dev, QemuConsole *src,
                             QemuInputEvent *evt)
 {
     struct XenInput *xenfb = (struct XenInput *)dev;
-    int qcode = evt->key.key;
+    int qcode = qemu_input_linux_to_qcode(evt->key.key);
     int lnx;
 
     if (qcode < qemu_input_map_qcode_to_linux_len) {
index db3c77775009319576b099b9c24bbd25cca42fe7..060481d0db6d0d457e19708604b54f719034e463 100644 (file)
@@ -311,7 +311,7 @@ static void adb_keyboard_event(DeviceState *dev, QemuConsole *src,
     KBDState *s = (KBDState *)dev;
     int qcode, keycode;
 
-    qcode = evt->key.key;
+    qcode = qemu_input_linux_to_qcode(evt->key.key);
     if (qcode >= ARRAY_SIZE(qcode_to_adb_keycode)) {
         return;
     }
index 31f6331c7d7e738af3f5c375c96973c452ee0966..013840562f6020bd87d00fb0ba933ba951b7d757 100644 (file)
@@ -224,10 +224,11 @@ static void hid_keyboard_event(DeviceState *dev, QemuConsole *src,
                                QemuInputEvent *evt)
 {
     HIDState *hs = (HIDState *)dev;
+    int qcode = qemu_input_linux_to_qcode(evt->key.key);
     int scancodes[3], i, count;
     int slot;
 
-    count = qemu_input_qcode_to_scancode(evt->key.key, evt->key.down,
+    count = qemu_input_qcode_to_scancode(qcode, evt->key.down,
                                          scancodes);
     if (hs->n + count > QUEUE_LENGTH) {
         trace_hid_kbd_queue_full();
index 9090a0427bd8457ab7be5249d517e322bc8a649b..93c3c7372054058a9deb99d04db1cf9bc9ed2238 100644 (file)
@@ -324,7 +324,7 @@ static void ps2_keyboard_event(DeviceState *dev, QemuConsole *src,
 
     qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
     assert(evt->type == INPUT_EVENT_KIND_KEY);
-    qcode = evt->key.key;
+    qcode = qemu_input_linux_to_qcode(evt->key.key);
 
     mod = ps2_modifier_bit(qcode);
     trace_ps2_keyboard_event(s, qcode, evt->key.down, mod,
index 6f42c46ddad328a93ef4063927e871259de70a4d..25769fc26168d964d1cbe8a2538d0414d321d7dd 100644 (file)
@@ -19,7 +19,7 @@ static void stellaris_gamepad_event(DeviceState *dev, QemuConsole *src,
                                     QemuInputEvent *evt)
 {
     StellarisGamepad *s = STELLARIS_GAMEPAD(dev);
-    int qcode = evt->key.key;
+    int qcode = qemu_input_linux_to_qcode(evt->key.key);
     int i;
 
     for (i = 0; i < s->num_buttons; i++) {
index d48be1ea211ec859142fdc671b7e7e95e07be1de..1d2e922567ab4ca63303acaf95eb10eafe60e367 100644 (file)
@@ -87,7 +87,7 @@ static void virtio_input_handle_event(DeviceState *dev, QemuConsole *src,
 
     switch (evt->type) {
     case INPUT_EVENT_KIND_KEY:
-        qcode = evt->key.key;
+        qcode = qemu_input_linux_to_qcode(evt->key.key);
         if (qcode < qemu_input_map_qcode_to_linux_len &&
             qemu_input_map_qcode_to_linux[qcode]) {
             event.type  = cpu_to_le16(EV_KEY);
index 39f223d021148fabd251d41da10f09816561ef5c..7efbd806b7c810896ee690484ccf7705b49c8bcb 100644 (file)
@@ -248,7 +248,7 @@ static void nextkbd_event(DeviceState *dev, QemuConsole *src,
     NextKBDState *s = NEXTKBD(dev);
     int qcode, keycode;
 
-    qcode = evt->key.key;
+    qcode = qemu_input_linux_to_qcode(evt->key.key);
     if (qcode >= ARRAY_SIZE(qcode_to_nextkbd_keycode)) {
         return;
     }
index 3c3dfa7b59dfc23e8d3335b2ede31db808a2cde7..e76dd4b172aa89527ac28291a7982649dabe36e6 100644 (file)
@@ -19,7 +19,7 @@ typedef struct QemuInputHandler QemuInputHandler;
 typedef struct QemuInputHandlerState QemuInputHandlerState;
 
 typedef struct QemuInputKeyEvent {
-    QKeyCode key;
+    unsigned int key;
     bool down;
 } QemuInputKeyEvent;
 
@@ -59,13 +59,18 @@ void qemu_input_event_sync(void);
 void qemu_input_event_sync_impl(void);
 
 void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down);
+void qemu_input_event_send_key_linux(QemuConsole *src, unsigned int lnx,
+                                     bool down);
 void qemu_input_event_send_key_number(QemuConsole *src, int num, bool down);
 void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down);
 void qemu_input_event_send_key_delay(uint32_t delay_ms);
 int qemu_input_key_number_to_qcode(unsigned int nr);
+unsigned int qemu_input_key_number_to_linux(unsigned int nr);
 int qemu_input_key_value_to_number(const KeyValue *value);
 int qemu_input_key_value_to_qcode(const KeyValue *value);
+unsigned int qemu_input_key_value_to_linux(const KeyValue *value);
 int qemu_input_qcode_to_scancode(QKeyCode qcode, bool down, int *codes);
+int qemu_input_linux_to_scancode(unsigned int lnx, bool down, int *codes);
 int qemu_input_linux_to_qcode(unsigned int lnx);
 
 void qemu_input_queue_btn(QemuConsole *src, InputButton btn, bool down);
@@ -107,52 +112,94 @@ void qemu_remove_mouse_mode_change_notifier(Notifier *notify);
 extern const guint qemu_input_map_atset1_to_qcode_len;
 extern const guint16 qemu_input_map_atset1_to_qcode[];
 
+extern const guint qemu_input_map_atset1_to_linux_len;
+extern const guint16 qemu_input_map_atset1_to_linux[];
+
 extern const guint qemu_input_map_linux_to_qcode_len;
 extern const guint16 qemu_input_map_linux_to_qcode[];
 
 extern const guint qemu_input_map_qcode_to_atset1_len;
 extern const guint16 qemu_input_map_qcode_to_atset1[];
 
+extern const guint qemu_input_map_linux_to_atset1_len;
+extern const guint16 qemu_input_map_linux_to_atset1[];
+
 extern const guint qemu_input_map_qcode_to_atset2_len;
 extern const guint16 qemu_input_map_qcode_to_atset2[];
 
+extern const guint qemu_input_map_linux_to_atset2_len;
+extern const guint16 qemu_input_map_linux_to_atset2[];
+
 extern const guint qemu_input_map_qcode_to_atset3_len;
 extern const guint16 qemu_input_map_qcode_to_atset3[];
 
+extern const guint qemu_input_map_linux_to_atset3_len;
+extern const guint16 qemu_input_map_linux_to_atset3[];
+
 extern const guint qemu_input_map_qcode_to_linux_len;
 extern const guint16 qemu_input_map_qcode_to_linux[];
 
 extern const guint qemu_input_map_qcode_to_qnum_len;
 extern const guint16 qemu_input_map_qcode_to_qnum[];
 
+extern const guint qemu_input_map_linux_to_qnum_len;
+extern const guint16 qemu_input_map_linux_to_qnum[];
+
 extern const guint qemu_input_map_qcode_to_sun_len;
 extern const guint16 qemu_input_map_qcode_to_sun[];
 
+extern const guint qemu_input_map_linux_to_sun_len;
+extern const guint16 qemu_input_map_linux_to_sun[];
+
 extern const guint qemu_input_map_qnum_to_qcode_len;
 extern const guint16 qemu_input_map_qnum_to_qcode[];
 
+extern const guint qemu_input_map_qnum_to_linux_len;
+extern const guint16 qemu_input_map_qnum_to_linux[];
+
 extern const guint qemu_input_map_usb_to_qcode_len;
 extern const guint16 qemu_input_map_usb_to_qcode[];
 
+extern const guint qemu_input_map_usb_to_linux_len;
+extern const guint16 qemu_input_map_usb_to_linux[];
+
 extern const guint qemu_input_map_win32_to_qcode_len;
 extern const guint16 qemu_input_map_win32_to_qcode[];
 
+extern const guint qemu_input_map_win32_to_linux_len;
+extern const guint16 qemu_input_map_win32_to_linux[];
+
 extern const guint qemu_input_map_x11_to_qcode_len;
 extern const guint16 qemu_input_map_x11_to_qcode[];
 
+extern const guint qemu_input_map_x11_to_linux_len;
+extern const guint16 qemu_input_map_x11_to_linux[];
+
 extern const guint qemu_input_map_xorgevdev_to_qcode_len;
 extern const guint16 qemu_input_map_xorgevdev_to_qcode[];
 
 extern const guint qemu_input_map_xorgkbd_to_qcode_len;
 extern const guint16 qemu_input_map_xorgkbd_to_qcode[];
 
+extern const guint qemu_input_map_xorgkbd_to_linux_len;
+extern const guint16 qemu_input_map_xorgkbd_to_linux[];
+
 extern const guint qemu_input_map_xorgxquartz_to_qcode_len;
 extern const guint16 qemu_input_map_xorgxquartz_to_qcode[];
 
+extern const guint qemu_input_map_xorgxquartz_to_linux_len;
+extern const guint16 qemu_input_map_xorgxquartz_to_linux[];
+
 extern const guint qemu_input_map_xorgxwin_to_qcode_len;
 extern const guint16 qemu_input_map_xorgxwin_to_qcode[];
 
+extern const guint qemu_input_map_xorgxwin_to_linux_len;
+extern const guint16 qemu_input_map_xorgxwin_to_linux[];
+
 extern const guint qemu_input_map_osx_to_qcode_len;
 extern const guint16 qemu_input_map_osx_to_qcode[];
 
+extern const guint qemu_input_map_osx_to_linux_len;
+extern const guint16 qemu_input_map_osx_to_linux[];
+
 #endif /* INPUT_H */
index f1ee678ef7262118c612395406a0d47c9bc5b52b..acf0993c7285e77813578875e1cff0fd35e5714b 100644 (file)
@@ -24,7 +24,7 @@ void replay_save_input_event(QemuInputEvent *evt)
     switch (evt->type) {
     case INPUT_EVENT_KIND_KEY:
         replay_put_dword(KEY_VALUE_KIND_QCODE);
-        replay_put_dword(evt->key.key);
+        replay_put_dword(qemu_input_linux_to_qcode(evt->key.key));
         replay_put_byte(evt->key.down);
         break;
     case INPUT_EVENT_KIND_BTN:
@@ -55,20 +55,25 @@ void replay_save_input_event(QemuInputEvent *evt)
 QemuInputEvent *replay_read_input_event(void)
 {
     QemuInputEvent *evt = g_new(QemuInputEvent, 1);
+    int qcode;
 
     evt->type = replay_get_dword();
     switch (evt->type) {
     case INPUT_EVENT_KIND_KEY:
         switch (replay_get_dword()) {
         case KEY_VALUE_KIND_NUMBER:
-            evt->key.key = qemu_input_key_number_to_qcode(replay_get_qword());
+            qcode = qemu_input_key_number_to_qcode(replay_get_qword());
             evt->key.down = replay_get_byte();
             break;
         case KEY_VALUE_KIND_QCODE:
-            evt->key.key = (QKeyCode)replay_get_dword();
+            qcode = (QKeyCode)replay_get_dword();
             evt->key.down = replay_get_byte();
             break;
+        default:
+            g_assert_not_reached();
         }
+        evt->key.key = qcode < qemu_input_map_qcode_to_linux_len ?
+                       qemu_input_map_qcode_to_linux[qcode] : 0;
         break;
     case INPUT_EVENT_KIND_BTN:
         evt->btn.button = (InputButton)replay_get_dword();
index 2313b0a7c7713fc3c6261e5518eb6ea0220ef764..90e2e79d1ea74e8fee17c4b7da9519c66e55e17a 100644 (file)
@@ -82,11 +82,18 @@ void qemu_input_event_send_key_delay(uint32_t delay_ms)
 }
 
 void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down)
+{
+    unsigned int lnx = qemu_input_map_qcode_to_linux[q];
+    qemu_input_event_send_key_linux(src, lnx, down);
+}
+
+void qemu_input_event_send_key_linux(QemuConsole *src, unsigned int lnx,
+                                     bool down)
 {
     QemuDBusDisplay1Keyboard *kbd;
     guint qnum;
 
-    trace_qemu_vnc_key_event(q, down);
+    trace_qemu_vnc_key_event(lnx, down);
 
     if (!src) {
         return;
@@ -96,10 +103,10 @@ void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down)
         return;
     }
 
-    if (q >= qemu_input_map_qcode_to_qnum_len) {
+    if (lnx >= qemu_input_map_linux_to_qnum_len) {
         return;
     }
-    qnum = qemu_input_map_qcode_to_qnum[q];
+    qnum = qemu_input_map_linux_to_qnum[lnx];
 
     if (down) {
         qemu_dbus_display1_keyboard_call_press(
index e3b550de10e3f3b36ba5c5dc0e74f0f2741de9b0..570062984a42942c4b6555bd22ceb53dbf782f91 100644 (file)
@@ -12,7 +12,7 @@ qemu_vnc_cursor_define(int width, int height, int hot_x, int hot_y) "w=%d h=%d h
 qemu_vnc_input_abs(uint32_t x, uint32_t y) "x=%u y=%u"
 qemu_vnc_input_btn(int button, bool press) "button=%d press=%d"
 qemu_vnc_input_rel(int dx, int dy) "dx=%d dy=%d"
-qemu_vnc_key_event(int qcode, bool down) "qcode=%d down=%d"
+qemu_vnc_key_event(unsigned int lnx, bool down) "lnx=%u down=%d"
 qemu_vnc_owner_appeared(const char *name) "peer=%s"
 qemu_vnc_owner_vanished(const char *name) "peer=%s"
 qemu_vnc_scanout(uint32_t width, uint32_t height, uint32_t stride, uint32_t format) "w=%u h=%u stride=%u fmt=0x%x"
index 2f6d431c82463706c07db327f961b26b71b5bb7e..2b77ef09fd6650d5b561f7a7226b24dde711781a 100644 (file)
@@ -5,22 +5,36 @@
 #include "standard-headers/linux/input.h"
 
 #include "ui/input-keymap-atset1-to-qcode.c.inc"
+#include "ui/input-keymap-atset1-to-linux.c.inc"
 #include "ui/input-keymap-linux-to-qcode.c.inc"
 #include "ui/input-keymap-qcode-to-atset1.c.inc"
+#include "ui/input-keymap-linux-to-atset1.c.inc"
 #include "ui/input-keymap-qcode-to-atset2.c.inc"
+#include "ui/input-keymap-linux-to-atset2.c.inc"
 #include "ui/input-keymap-qcode-to-atset3.c.inc"
+#include "ui/input-keymap-linux-to-atset3.c.inc"
 #include "ui/input-keymap-qcode-to-linux.c.inc"
 #include "ui/input-keymap-qcode-to-qnum.c.inc"
+#include "ui/input-keymap-linux-to-qnum.c.inc"
 #include "ui/input-keymap-qcode-to-sun.c.inc"
+#include "ui/input-keymap-linux-to-sun.c.inc"
 #include "ui/input-keymap-qnum-to-qcode.c.inc"
+#include "ui/input-keymap-qnum-to-linux.c.inc"
 #include "ui/input-keymap-usb-to-qcode.c.inc"
+#include "ui/input-keymap-usb-to-linux.c.inc"
 #include "ui/input-keymap-win32-to-qcode.c.inc"
+#include "ui/input-keymap-win32-to-linux.c.inc"
 #include "ui/input-keymap-x11-to-qcode.c.inc"
+#include "ui/input-keymap-x11-to-linux.c.inc"
 #include "ui/input-keymap-xorgevdev-to-qcode.c.inc"
 #include "ui/input-keymap-xorgkbd-to-qcode.c.inc"
+#include "ui/input-keymap-xorgkbd-to-linux.c.inc"
 #include "ui/input-keymap-xorgxquartz-to-qcode.c.inc"
+#include "ui/input-keymap-xorgxquartz-to-linux.c.inc"
 #include "ui/input-keymap-xorgxwin-to-qcode.c.inc"
+#include "ui/input-keymap-xorgxwin-to-linux.c.inc"
 #include "ui/input-keymap-osx-to-qcode.c.inc"
+#include "ui/input-keymap-osx-to-linux.c.inc"
 
 int qemu_input_linux_to_qcode(unsigned int lnx)
 {
@@ -45,29 +59,49 @@ int qemu_input_key_value_to_number(const KeyValue *value)
 
 int qemu_input_key_number_to_qcode(unsigned int nr)
 {
-    if (nr >= qemu_input_map_qnum_to_qcode_len) {
-        return 0;
+    return qemu_input_linux_to_qcode(qemu_input_key_number_to_linux(nr));
+}
+
+unsigned int qemu_input_key_number_to_linux(unsigned int nr)
+{
+    if (nr >= qemu_input_map_qnum_to_linux_len) {
+        return KEY_RESERVED;
     }
-    return qemu_input_map_qnum_to_qcode[nr];
+    return qemu_input_map_qnum_to_linux[nr];
 }
 
 int qemu_input_key_value_to_qcode(const KeyValue *value)
 {
-    if (value->type == KEY_VALUE_KIND_QCODE) {
-        return value->u.qcode.data;
-    } else {
-        assert(value->type == KEY_VALUE_KIND_NUMBER);
-        return qemu_input_key_number_to_qcode(value->u.number.data);
+    return qemu_input_linux_to_qcode(qemu_input_key_value_to_linux(value));
+}
+
+unsigned int qemu_input_key_value_to_linux(const KeyValue *value)
+{
+    switch (value->type) {
+    case KEY_VALUE_KIND_NUMBER:
+        return qemu_input_key_number_to_linux(value->u.number.data);
+
+    case KEY_VALUE_KIND_QCODE:
+        return qemu_input_map_qcode_to_linux[value->u.qcode.data];
+
+    default:
+        g_assert_not_reached();
     }
 }
 
 int qemu_input_qcode_to_scancode(QKeyCode qcode, bool down, int *codes)
 {
-    int keycode = qcode < qemu_input_map_qcode_to_qnum_len ?
-                  qemu_input_map_qcode_to_qnum[qcode] : 0;
+    return qemu_input_linux_to_scancode(qemu_input_map_qcode_to_linux[qcode],
+                                        down, codes);
+}
+
+int qemu_input_linux_to_scancode(unsigned int lnx, bool down, int *codes)
+{
+    int keycode = lnx < qemu_input_map_linux_to_qnum_len ?
+                  qemu_input_map_linux_to_qnum[lnx] : 0;
     int count = 0;
 
-    if (qcode == Q_KEY_CODE_PAUSE) {
+    if (lnx == KEY_PAUSE) {
         /* specific case */
         int v = down ? 0 : 0x80;
         codes[count++] = 0xe1;
index 9232dd7fdae9eb08e0d8b440b3e170d9ccb4d82e..aeb7bf35e196046c8aac588ca8ecff8e91276ee6 100644 (file)
@@ -165,25 +165,10 @@ void qmp_input_send_event(const char *device,
         evt.type = qapi->type;
 
         switch (qapi->type) {
-        case INPUT_EVENT_KIND_KEY: {
-            KeyValue *key = qapi->u.key.data->key;
-            QKeyCode code;
-
-            switch (key->type) {
-            case KEY_VALUE_KIND_NUMBER:
-                code = qemu_input_key_number_to_qcode(key->u.number.data);
-                break;
-            case KEY_VALUE_KIND_QCODE:
-                code = key->u.qcode.data;
-                break;
-            default:
-                g_assert_not_reached();
-            }
-
-            evt.key.key = code;
+        case INPUT_EVENT_KIND_KEY:
+            evt.key.key = qemu_input_key_value_to_linux(qapi->u.key.data->key);
             evt.key.down = qapi->u.key.data->down;
             break;
-        }
 
         case INPUT_EVENT_KIND_BTN:
             evt.btn = *qapi->u.btn.data;
@@ -226,7 +211,7 @@ static void qemu_input_event_trace(QemuConsole *src, QemuInputEvent *evt)
     switch (evt->type) {
     case INPUT_EVENT_KIND_KEY:
         key = &evt->key;
-        name = QKeyCode_str(key->key);
+        name = QKeyCode_str(qemu_input_linux_to_qcode(key->key));
         trace_input_event_key_qcode(idx, name, key->down);
         break;
     case INPUT_EVENT_KIND_BTN:
@@ -343,19 +328,6 @@ void qemu_input_event_send_impl(QemuConsole *src, QemuInputEvent *evt)
 
 void qemu_input_event_send(QemuConsole *src, QemuInputEvent *evt)
 {
-    /*
-     * 'sysrq' was mistakenly added to hack around the fact that
-     * the ps2 driver was not generating correct scancodes sequences
-     * when 'alt+print' was pressed. This flaw is now fixed and the
-     * 'sysrq' key serves no further purpose. We normalize it to
-     * 'print', so that downstream receivers of the event don't
-     * need to deal with this mistake
-     */
-    if (evt->type == INPUT_EVENT_KIND_KEY &&
-        evt->key.key == Q_KEY_CODE_SYSRQ) {
-        evt->key.key = Q_KEY_CODE_PRINT;
-    }
-
     if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) {
         return;
     }
@@ -390,17 +362,24 @@ void qemu_input_event_sync(void)
 }
 
 void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down)
+{
+    unsigned int lnx = qemu_input_key_value_to_linux(key);
+
+    g_free(key);
+    qemu_input_event_send_key_linux(src, lnx, down);
+}
+
+void qemu_input_event_send_key_linux(QemuConsole *src, unsigned int lnx,
+                                     bool down)
 {
     QemuInputEvent evt = {
         .type = INPUT_EVENT_KIND_KEY,
         .key = {
-            .key = qemu_input_key_value_to_qcode(key),
+            .key = lnx,
             .down = down,
         },
     };
 
-    g_free(key);
-
     if (QTAILQ_EMPTY(&kbd_queue)) {
         qemu_input_event_send(src, &evt);
         qemu_input_event_sync();
@@ -412,8 +391,8 @@ void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down)
 
 void qemu_input_event_send_key_number(QemuConsole *src, int num, bool down)
 {
-    QKeyCode code = qemu_input_key_number_to_qcode(num);
-    qemu_input_event_send_key_qcode(src, code, down);
+    unsigned int lnx = qemu_input_key_number_to_linux(num);
+    qemu_input_event_send_key_linux(src, lnx, down);
 }
 
 void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down)
index 1b8f71796e408bb64dc0f3b276b918981e9d692e..1504e27248f3a676ffe9bbbb265b2c2982f3c3d0 100644 (file)
@@ -1,21 +1,35 @@
 keymaps = [
   ['atset1', 'qcode'],
+  ['atset1', 'linux'],
   ['linux', 'qcode'],
   ['qcode', 'atset1'],
+  ['linux', 'atset1'],
   ['qcode', 'atset2'],
+  ['linux', 'atset2'],
   ['qcode', 'atset3'],
+  ['linux', 'atset3'],
   ['qcode', 'linux'],
   ['qcode', 'qnum'],
+  ['linux', 'qnum'],
   ['qcode', 'sun'],
+  ['linux', 'sun'],
   ['qnum', 'qcode'],
+  ['qnum', 'linux'],
   ['usb', 'qcode'],
+  ['usb', 'linux'],
   ['win32', 'qcode'],
+  ['win32', 'linux'],
   ['x11', 'qcode'],
+  ['x11', 'linux'],
   ['xorgevdev', 'qcode'],
   ['xorgkbd', 'qcode'],
+  ['xorgkbd', 'linux'],
   ['xorgxquartz', 'qcode'],
+  ['xorgxquartz', 'linux'],
   ['xorgxwin', 'qcode'],
+  ['xorgxwin', 'linux'],
   ['osx', 'qcode'],
+  ['osx', 'linux'],
 ]
 
 if have_system or xkbcommon.found()