diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2012-02-08 13:18:37 +0100 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2012-02-10 09:58:33 +0100 |
commit | 7bc9318bfb68b2d773449a55d4fa800d0fdb0918 (patch) | |
tree | 49b9e5f1878b8b3ee822e70c9e37731ea3953eac /ui/vnc.c | |
parent | 8cf364898cfe4ae761f2253e91a040633d6f87be (diff) |
vnc: lift modifier keys on client disconnect.
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 <kraxel@redhat.com>
Diffstat (limited to 'ui/vnc.c')
-rw-r--r-- | ui/vnc.c | 25 |
1 files changed, 25 insertions, 0 deletions
@@ -46,6 +46,7 @@ static VncDisplay *vnc_display; /* needed for info vnc */ static DisplayChangeListener *dcl; static int vnc_cursor_define(VncState *vs); +static void vnc_release_modifiers(VncState *vs); static void vnc_set_share_mode(VncState *vs, VncShareMode mode) { @@ -1051,6 +1052,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); @@ -1679,6 +1681,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; |