Logging/replaying implementation of the mouse and keyboard input. Signed-off-by: Pavel Dovgalyuk <pavel.dovga...@gmail.com> ---
diff --git a/include/ui/input.h b/include/ui/input.h index 5d5ac00..d06a12d 100644 --- a/include/ui/input.h +++ b/include/ui/input.h @@ -33,7 +33,9 @@ void qemu_input_handler_bind(QemuInputHandlerState *s, const char *device_id, int head, Error **errp); void qemu_input_event_send(QemuConsole *src, InputEvent *evt); +void qemu_input_event_send_impl(QemuConsole *src, InputEvent *evt); void qemu_input_event_sync(void); +void qemu_input_event_sync_impl(void); InputEvent *qemu_input_event_new_key(KeyValue *key, bool down); void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down); diff --git a/ui/input.c b/ui/input.c index 89d9db7..0605c83 --- a/ui/input.c +++ b/ui/input.c @@ -2,6 +2,7 @@ #include "sysemu/sysemu.h" #include "qapi-types.h" #include "qmp-commands.h" +#include "replay/replay.h" #include "trace.h" #include "ui/input.h" #include "ui/console.h" @@ -258,19 +259,15 @@ static void qemu_input_queue_sync(struct QemuInputEventQueueHead *queue) QTAILQ_INSERT_TAIL(queue, item, node); } -void qemu_input_event_send(QemuConsole *src, InputEvent *evt) +void qemu_input_event_send_impl(QemuConsole *src, InputEvent *evt) { QemuInputHandlerState *s; - if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) { - return; - } - qemu_input_event_trace(src, evt); /* pre processing */ if (graphic_rotate && (evt->kind == INPUT_EVENT_KIND_ABS)) { - qemu_input_transform_abs_rotate(evt); + qemu_input_transform_abs_rotate(evt); } /* send event */ @@ -282,14 +279,25 @@ void qemu_input_event_send(QemuConsole *src, InputEvent *evt) s->events++; } -void qemu_input_event_sync(void) +void qemu_input_event_send(QemuConsole *src, InputEvent *evt) { - QemuInputHandlerState *s; - if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) { return; } + if (replay_mode == REPLAY_PLAY && replay_get_play_submode() != REPLAY_PLAY_CHANGED) { + /* Nothing */ + } else if (replay_mode == REPLAY_SAVE) { + replay_add_event(REPLAY_ASYNC_EVENT_INPUT, evt); + } else { + qemu_input_event_send_impl(src, evt); + } +} + +void qemu_input_event_sync_impl(void) +{ + QemuInputHandlerState *s; + trace_input_event_sync(); QTAILQ_FOREACH(s, &handlers, node) { @@ -303,6 +311,22 @@ void qemu_input_event_sync(void) } } +void qemu_input_event_sync(void) +{ + if (!runstate_is_running() && !runstate_check(RUN_STATE_SUSPENDED)) { + return; + } + + if (replay_mode == REPLAY_PLAY && replay_get_play_submode() != REPLAY_PLAY_CHANGED) { + /* Nothing */ + } else if (replay_mode == REPLAY_SAVE) { + replay_add_event(REPLAY_ASYNC_EVENT_INPUT_SYNC, NULL); + } else { + qemu_input_event_sync_impl(); + } +} + + InputEvent *qemu_input_event_new_key(KeyValue *key, bool down) { InputEvent *evt = g_new0(InputEvent, 1); @@ -317,13 +341,20 @@ void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down) { InputEvent *evt; evt = qemu_input_event_new_key(key, down); - if (QTAILQ_EMPTY(&kbd_queue)) { - qemu_input_event_send(src, evt); - qemu_input_event_sync(); + if (replay_mode == REPLAY_PLAY && replay_get_play_submode() != REPLAY_PLAY_CHANGED) { qapi_free_InputEvent(evt); } else { - qemu_input_queue_event(&kbd_queue, src, evt); - qemu_input_queue_sync(&kbd_queue); + if (QTAILQ_EMPTY(&kbd_queue)) { + qemu_input_event_send(src, evt); + qemu_input_event_sync(); + } else { + if (replay_mode != REPLAY_NONE) { + fprintf(stderr, "Input queue is not supported in replay\n"); + exit(1); + } + qemu_input_queue_event(&kbd_queue, src, evt); + qemu_input_queue_sync(&kbd_queue); + } } } @@ -349,6 +380,10 @@ void qemu_input_event_send_key_delay(uint32_t delay_ms) kbd_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, qemu_input_queue_process, &kbd_queue); } + if (replay_mode != REPLAY_NONE) { + fprintf(stderr, "Input queue is not supported in replay\n"); + exit(1); + } qemu_input_queue_delay(&kbd_queue, kbd_timer, delay_ms ? delay_ms : kbd_default_delay_ms); } @@ -368,7 +403,9 @@ void qemu_input_queue_btn(QemuConsole *src, InputButton btn, bool down) InputEvent *evt; evt = qemu_input_event_new_btn(btn, down); qemu_input_event_send(src, evt); - qapi_free_InputEvent(evt); + if (replay_mode != REPLAY_SAVE) { + qapi_free_InputEvent(evt); + } } void qemu_input_update_buttons(QemuConsole *src, uint32_t *button_map, @@ -386,6 +423,7 @@ void qemu_input_update_buttons(QemuConsole *src, uint32_t *button_map, } } + bool qemu_input_is_absolute(void) { QemuInputHandlerState *s; @@ -403,6 +441,7 @@ int qemu_input_scale_axis(int value, int size_in, int size_out) return (int64_t)value * (size_out - 1) / (size_in - 1); } + InputEvent *qemu_input_event_new_move(InputEventKind kind, InputAxis axis, int value) { @@ -421,7 +460,9 @@ void qemu_input_queue_rel(QemuConsole *src, InputAxis axis, int value) InputEvent *evt; evt = qemu_input_event_new_move(INPUT_EVENT_KIND_REL, axis, value); qemu_input_event_send(src, evt); - qapi_free_InputEvent(evt); + if (replay_mode != REPLAY_SAVE) { + qapi_free_InputEvent(evt); + } } void qemu_input_queue_abs(QemuConsole *src, InputAxis axis, int value, int size) @@ -430,7 +471,9 @@ void qemu_input_queue_abs(QemuConsole *src, InputAxis axis, int value, int size) int scaled = qemu_input_scale_axis(value, size, INPUT_EVENT_ABS_SIZE); evt = qemu_input_event_new_move(INPUT_EVENT_KIND_ABS, axis, scaled); qemu_input_event_send(src, evt); - qapi_free_InputEvent(evt); + if (replay_mode != REPLAY_SAVE) { + qapi_free_InputEvent(evt); + } } void qemu_input_check_mode_change(void)