From 82a60a9917e14e182c40bfc269d093d245a3b6f8 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Wed, 21 Mar 2012 10:43:01 +0100 Subject: [PATCH 4/4] vnc: lift modifier keys on client disconnect RH-Author: Laszlo Ersek Message-id: <1332326581-7609-1-git-send-email-lersek@redhat.com> Patchwork-id: 38777 O-Subject: [RHEL-6.3 qemu-kvm PATCH v2 2/2] vnc: lift modifier keys on client disconnect Bugzilla: 785963 RH-Acked-by: Gerd Hoffmann RH-Acked-by: Amos Kong RH-Acked-by: Alex Williamson From: Gerd Hoffmann For any modifier key (shift, ctrl, alt) still pressed on disconnect inject a key-up event into the guest. The vnc client is gone, it will not do that, so qemu has to do it instead. Without this keys will get stuck, making the guest act in weird ways after reconnecting. Reproducer: exit vnc client via Alt-F4, guest continues to see the pressed alt key and will not react to key events in any useful way until you tap the alt key once to unstuck it. Signed-off-by: Gerd Hoffmann (cherry picked from commit 7bc9318bfb68b2d773449a55d4fa800d0fdb0918) Conflicts: vnc.c v1->v2: adapted to 0f8cc78d ("vnc: Migrate to using QTAILQ instead of custom implementation"). Signed-off-by: Laszlo Ersek --- vnc.c | 25 +++++++++++++++++++++++++ 1 files changed, 25 insertions(+), 0 deletions(-) Signed-off-by: Michal Novotny --- vnc.c | 25 +++++++++++++++++++++++++ 1 files changed, 25 insertions(+), 0 deletions(-) diff --git a/vnc.c b/vnc.c index 5df8467..15cb39c 100644 --- a/vnc.c +++ b/vnc.c @@ -45,6 +45,7 @@ } \ } +static void vnc_release_modifiers(VncState *vs); static VncDisplay *vnc_display; /* needed for info vnc */ static DisplayChangeListener *dcl; @@ -1110,6 +1111,7 @@ static void vnc_disconnect_finish(VncState *vs) vnc_sasl_client_cleanup(vs); #endif /* CONFIG_VNC_SASL */ audio_del(vs); + vnc_release_modifiers(vs); QTAILQ_REMOVE(&vs->vd->clients, vs, next); @@ -1703,6 +1705,29 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym) } } +static void vnc_release_modifiers(VncState *vs) +{ + static const int keycodes[] = { + /* shift, control, alt keys, both left & right */ + 0x2a, 0x36, 0x1d, 0x9d, 0x38, 0xb8, + }; + int i, keycode; + + if (!is_graphic_console()) { + return; + } + for (i = 0; i < ARRAY_SIZE(keycodes); i++) { + keycode = keycodes[i]; + if (!vs->modifiers_state[keycode]) { + continue; + } + if (keycode & SCANCODE_GREY) { + kbd_put_keycode(SCANCODE_EMUL0); + } + kbd_put_keycode(keycode | SCANCODE_UP); + } +} + static void key_event(VncState *vs, int down, uint32_t sym) { int keycode; -- 1.7.7.6