legacy kbd event handlers are registered in the new core, so they receive events from the new input core code. keycode -> scancode translation needed here.
legacy kbd_put_keycode() sends events to the new core. scancode -> keycode translation needed here. So with this patch the new input core is fully functional for keyboard events. New + legacy interfaces can be mixed in any way. Signed-off-by: Gerd Hoffmann <kra...@redhat.com> --- ui/input-legacy.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 10 deletions(-) diff --git a/ui/input-legacy.c b/ui/input-legacy.c index 1c70f60..80f4f5c 100644 --- a/ui/input-legacy.c +++ b/ui/input-legacy.c @@ -29,6 +29,7 @@ #include "qmp-commands.h" #include "qapi-types.h" #include "ui/keymaps.h" +#include "ui/input.h" struct QEMUPutMouseEntry { QEMUPutMouseEvent *qemu_put_mouse_event; @@ -45,7 +46,7 @@ struct QEMUPutMouseEntry { struct QEMUPutKbdEntry { QEMUPutKBDEvent *put_kbd; void *opaque; - QTAILQ_ENTRY(QEMUPutKbdEntry) next; + QemuInputHandlerState *s; }; struct QEMUPutLEDEntry { @@ -56,8 +57,6 @@ struct QEMUPutLEDEntry { static QTAILQ_HEAD(, QEMUPutLEDEntry) led_handlers = QTAILQ_HEAD_INITIALIZER(led_handlers); -static QTAILQ_HEAD(, QEMUPutKbdEntry) kbd_handlers = - QTAILQ_HEAD_INITIALIZER(kbd_handlers); static QTAILQ_HEAD(, QEMUPutMouseEntry) mouse_handlers = QTAILQ_HEAD_INITIALIZER(mouse_handlers); static NotifierList mouse_mode_notifiers = @@ -312,20 +311,56 @@ void qmp_send_key(KeyValueList *keys, bool has_hold_time, int64_t hold_time, muldiv64(get_ticks_per_sec(), hold_time, 1000)); } +static void legacy_kbd_event(DeviceState *dev, QemuConsole *src, + InputEvent *evt) +{ + QEMUPutKbdEntry *entry = (QEMUPutKbdEntry *)dev; + int keycode = keycode_from_keyvalue(evt->key->key); + + if (!entry || !entry->put_kbd) { + return; + } + if (evt->key->key->kind == KEY_VALUE_KIND_QCODE && + evt->key->key->qcode == Q_KEY_CODE_PAUSE) { + /* specific case */ + int v = evt->key->down ? 0 : 0x80; + entry->put_kbd(entry->opaque, 0xe1); + entry->put_kbd(entry->opaque, 0x1d | v); + entry->put_kbd(entry->opaque, 0x45 | v); + return; + } + if (keycode & SCANCODE_GREY) { + entry->put_kbd(entry->opaque, SCANCODE_EMUL0); + keycode &= ~SCANCODE_GREY; + } + if (!evt->key->down) { + keycode |= SCANCODE_UP; + } + entry->put_kbd(entry->opaque, keycode); +} + +static QemuInputHandler legacy_kbd_handler = { + .name = "legacy-kbd", + .mask = INPUT_EVENT_MASK_KEY, + .event = legacy_kbd_event, +}; + QEMUPutKbdEntry *qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque) { QEMUPutKbdEntry *entry; - entry = g_malloc0(sizeof(QEMUPutKbdEntry)); + entry = g_new0(QEMUPutKbdEntry, 1); entry->put_kbd = func; entry->opaque = opaque; - QTAILQ_INSERT_HEAD(&kbd_handlers, entry, next); + entry->s = qemu_input_handler_register((DeviceState *)entry, + &legacy_kbd_handler); return entry; } void qemu_remove_kbd_event_handler(QEMUPutKbdEntry *entry) { - QTAILQ_REMOVE(&kbd_handlers, entry, next); + qemu_input_handler_unregister(entry->s); + g_free(entry); } static void check_mode_change(void) @@ -409,14 +444,25 @@ void qemu_remove_led_event_handler(QEMUPutLEDEntry *entry) void kbd_put_keycode(int keycode) { - QEMUPutKbdEntry *entry = QTAILQ_FIRST(&kbd_handlers); + static bool emul0; + bool up; - if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) { + if (keycode == SCANCODE_EMUL0) { + emul0 = true; return; } - if (entry && entry->put_kbd) { - entry->put_kbd(entry->opaque, keycode); + if (keycode & SCANCODE_UP) { + keycode &= ~SCANCODE_UP; + up = true; + } else { + up = false; + } + if (emul0) { + keycode |= SCANCODE_GREY; + emul0 = false; } + + qemu_input_event_send_key_number(NULL, keycode, !up); } void kbd_put_ledstate(int ledstate) -- 1.8.3.1