[quoted lines by Peter Maydell on 2014/05/25 at 10:11 +0100]
Ah, I see. Still, I think it makes more sense for the queue and delay
to be in the common key handling code, not in the curses frontend
specifically.
This patch, attached as qemu-kbddelay-1.patch, is a rework of the former curses
UI patch so that the delay applies to key events in general. A new option,
-kbddelay [duration=]msecs, controls it. As before, the default is 0, meaning
no delay, in which case the timer and queue aren't used thus retaining the
original behaviour.
--
Dave Mielke | 2213 Fox Crescent | The Bible is the very Word of God.
Phone: 1-613-726-0014 | Ottawa, Ontario | http://Mielke.cc/bible/
EMail: d...@mielke.cc | Canada K2A 1H7 | http://FamilyRadio.com/
diff --git a/include/ui/input.h b/include/ui/input.h
index 3d3d487..17c77c8 100644
--- a/include/ui/input.h
+++ b/include/ui/input.h
@@ -35,6 +35,7 @@ void qemu_input_event_sync(void);
InputEvent *qemu_input_event_new_key(KeyValue *key, bool down);
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);
+void qemu_input_event_set_keyboard_delay(uint64_t duration);
void qemu_input_event_send_key_qcode(QemuConsole *src, QKeyCode q, bool down);
int qemu_input_key_value_to_number(const KeyValue *value);
int qemu_input_key_value_to_qcode(const KeyValue *value);
diff --git a/qemu-options.hx b/qemu-options.hx
index c2c0823..5d0a8b1 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -262,6 +262,24 @@ de en-us fi fr-be hr it lv nl-be pt sl tr
The default is @code{en-us}.
ETEXI
+DEF(kbddelay, HAS_ARG, QEMU_OPTION_kbddelay,
+-kbddelay [duration=]msecs\n
+ensure a minimum delay between keyboard events\n
+duration: the minimum delay between keyboard events
(default: 0)\n,
+QEMU_ARCH_ALL)
+STEXI
+@item -kbddelay [duration=]@var{msecs}
+@findex -kbddelay
+Set the minimum delay between keyboard events to @var{msecs} milliseconds.
+The default is 0 (no minimum delay).
+This option exists in order to deal with problematic applications which run
+into trouble when keys are typed too quickly. Certain UIs, like curses,
+aggravate the problem because they must turn a single user keyboard action
into
+several keyboard events being delivered to the virtual machine. Only try this
+option if you encounter an unexpected keyboard input issue, for example the
+input not being recognized at all. A duration of 20 seems to be reasonable.
+ETEXI
+
DEF(audio-help, 0, QEMU_OPTION_audio_help,
-audio-help print list of audio drivers and their options\n,
diff --git a/ui/input.c b/ui/input.c
index fc91fba..eb6c1dd 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -188,7 +188,9 @@ InputEvent *qemu_input_event_new_key(KeyValue *key, bool
down)
return evt;
}
-void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down)
+static void qemu_input_event_send_key_immediate(QemuConsole *src,
+KeyValue *key,
+bool down)
{
InputEvent *evt;
evt = qemu_input_event_new_key(key, down);
@@ -197,6 +199,82 @@ void qemu_input_event_send_key(QemuConsole *src, KeyValue
*key, bool down)
qapi_free_InputEvent(evt);
}
+struct PendingKeyEvent {
+struct PendingKeyEvent *next;
+QemuConsole *src;
+KeyValue *key;
+bool down;
+};
+
+static struct PendingKeyEvent *firstPendingKeyEvent = NULL;
+static struct PendingKeyEvent *lastPendingKeyEvent = NULL;
+
+static unsigned long long pendingKeyEventDelay = 0;
+static QEMUTimer *pendingKeyEventTimer = NULL;
+
+static void qemu_input_begin_pending_key_event(void)
+{
+struct PendingKeyEvent *event = firstPendingKeyEvent;
+
+qemu_input_event_send_key_immediate(event-src, event-key, event-down);
+timer_mod(pendingKeyEventTimer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
pendingKeyEventDelay);
+}
+
+static void qemu_input_end_pending_key_event(void *opaque)
+{
+struct PendingKeyEvent *event = firstPendingKeyEvent;
+
+if ((firstPendingKeyEvent = event-next))
+{
+qemu_input_begin_pending_key_event();
+}
+else
+{
+lastPendingKeyEvent = NULL;
+}
+
+g_free(event);
+}
+
+void qemu_input_event_send_key(QemuConsole *src, KeyValue *key, bool down)
+{
+if (pendingKeyEventDelay)
+{
+struct PendingKeyEvent *event;
+
+event = g_malloc(sizeof(*event));
+event-next = NULL;
+event-src = src;
+event-key = key;
+event-down = down;
+
+if (lastPendingKeyEvent)
+{
+lastPendingKeyEvent-next = event;
+lastPendingKeyEvent = event;
+}
+else
+{
+if (!pendingKeyEventTimer)
+{
+pendingKeyEventTimer = timer_new_ms(QEMU_CLOCK_VIRTUAL,