aboutsummaryrefslogtreecommitdiff
path: root/ui/vnc.c
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2012-02-08 13:18:37 +0100
committerGerd Hoffmann <kraxel@redhat.com>2012-02-10 09:58:33 +0100
commit7bc9318bfb68b2d773449a55d4fa800d0fdb0918 (patch)
tree49b9e5f1878b8b3ee822e70c9e37731ea3953eac /ui/vnc.c
parent8cf364898cfe4ae761f2253e91a040633d6f87be (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.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/ui/vnc.c b/ui/vnc.c
index 83a9b15c50..02b71bcd2c 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -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;