(qemu) sendkey a 1000

Current design is that qemu only send one down event to guest,
and delay sometime, then send one up event. In this case, only
key can be identified by guest.

This patch changed qemu to intervally send down events to guest
in the hold time, the interval is 100ms.

(qemu) sendkey a 1000

qemu will send 9 down events, 1 up event to guest, we can see
9 'a' in guest screen.

Signed-off-by: Amos Kong <ak...@redhat.com>
---
This patch based on Luiz's qmp-unstable/queue/qmp

Signed-off-by: Amos Kong <ak...@redhat.com>
---
 hmp-commands.hx |    4 +++-
 qmp-commands.hx |    3 ++-
 ui/input.c      |   38 ++++++++++++++++++++++++++------------
 3 files changed, 31 insertions(+), 14 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index df44906..a16961e 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -557,7 +557,9 @@ STEXI
 
 Send @var{keys} to the guest. @var{keys} could be the name of the
 key or the raw value in hexadecimal format. Use @code{-} to press
-several keys simultaneously. Example:
+several keys simultaneously. The default hold time is 100, in the
+hold time, qemu will intervally send down events to guest, the
+interval is 100ms. Example:
 @example
 sendkey ctrl-alt-f1
 @end example
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 4d65422..081f736 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -348,7 +348,8 @@ Arguments:
 keys array:
     - "key": key sequence (a json-array of key enum values)
 
-- hold-time: time to delay key up events, milliseconds. Defaults to 100
+- hold-time: time to intervally send down events to guest, the interval
+             is 100ms. Defaults to 100 milliseconds
              (json-int, optional)
 
 Example:
diff --git a/ui/input.c b/ui/input.c
index ecfeb43..143c421 100644
--- a/ui/input.c
+++ b/ui/input.c
@@ -214,6 +214,7 @@ int index_from_keycode(int code)
 static int *keycodes;
 static int keycodes_size;
 static QEMUTimer *key_timer;
+static int rest_time;
 
 static int keycode_from_keyvalue(const KeyValue *value)
 {
@@ -232,8 +233,27 @@ static void free_keycodes(void)
     keycodes_size = 0;
 }
 
-static void release_keys(void *opaque)
+static void enter_keys(void *opaque)
 {
+    int i, time;
+
+    /* key down events */
+    for (i = 0; i < keycodes_size; i++) {
+        if (keycodes[i] & 0x80) {
+            kbd_put_keycode(0xe0);
+        }
+        kbd_put_keycode(keycodes[i] & 0x7f);
+    }
+
+    rest_time -= 100;
+    if (rest_time > 0) {
+        time = rest_time > 100 ? 100 : rest_time;
+        qemu_mod_timer(key_timer, qemu_get_clock_ns(vm_clock) +
+                       muldiv64(get_ticks_per_sec(), time, 1000));
+        return;
+    }
+
+    /* key up events */
     while (keycodes_size > 0) {
         if (keycodes[--keycodes_size] & 0x80) {
             kbd_put_keycode(0xe0);
@@ -251,20 +271,21 @@ void qmp_send_key(KeyValueList *keys, bool has_hold_time, 
int64_t hold_time,
     KeyValueList *p;
 
     if (!key_timer) {
-        key_timer = qemu_new_timer_ns(vm_clock, release_keys, NULL);
+        key_timer = qemu_new_timer_ns(vm_clock, enter_keys, NULL);
     }
 
     if (keycodes != NULL) {
         qemu_del_timer(key_timer);
-        release_keys(NULL);
+        enter_keys(NULL);
     }
 
     if (!has_hold_time) {
         hold_time = 100;
     }
 
+    rest_time = hold_time;
+
     for (p = keys; p != NULL; p = p->next) {
-        /* key down events */
         keycode = keycode_from_keyvalue(p->value);
         if (keycode < 0x01 || keycode > 0xff) {
             error_setg(errp, "invalid hex keycode 0x%x", keycode);
@@ -272,18 +293,11 @@ void qmp_send_key(KeyValueList *keys, bool has_hold_time, 
int64_t hold_time,
             return;
         }
 
-        if (keycode & 0x80) {
-            kbd_put_keycode(0xe0);
-        }
-        kbd_put_keycode(keycode & 0x7f);
-
         keycodes = g_realloc(keycodes, sizeof(int) * (keycodes_size + 1));
         keycodes[keycodes_size++] = keycode;
     }
 
-    /* delayed key up events */
-    qemu_mod_timer(key_timer, qemu_get_clock_ns(vm_clock) +
-                   muldiv64(get_ticks_per_sec(), hold_time, 1000));
+    enter_keys(NULL);
 }
 
 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
-- 
1.7.1


Reply via email to