From 89b274767a2b10cf07ab3826d771049de6dc6b9d Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann <kraxel@redhat.com> Date: Tue, 5 Jan 2010 16:47:48 -0200 Subject: [PATCH 3/5] kvm/vnc: improve capslock handling RH-Author: Gerd Hoffmann <kraxel@redhat.com> Message-id: <1262710068-6415-1-git-send-email-kraxel@redhat.com> Patchwork-id: 6077 O-Subject: [RHEL 5.5 PATCH] kvm/vnc: improve capslock handling Bugzilla: 517814 RH-Acked-by: Juan Quintela <quintela@redhat.com> RH-Acked-by: Markus Armbruster <armbru@redhat.com> RH-Acked-by: Kevin Wolf <kwolf@redhat.com> bz #517814 This patch squashes two related upstream commits together: When capslock is toggled while the vnc window hasn't the focus qemu will miss the state change. Add sanity checks for the capslock state and toggle it if needed, so hosts and guests idea of capslock state stay in sync. Simliar logic for numlock is present in qemu already. The capslock tracking logic added by commit 6b1325029d80455b9da7cd7bd84a88cb915b867c doesn't work correctly for vnc clients without EXT_KEY_EVENT support. The reason is that qemu converts keysyms for letters to lowercase for the keysym2scancode lookup. It then also passes the lowercase value down to do_key_event(), but the capslock tracking code needs it with the correct case to work properly. This patch adds a new variable for the lowercase keysym so we'll keep the unmodified value for do_key_event(). --- qemu/vnc.c | 29 ++++++++++++++++++++++++++--- 1 files changed, 26 insertions(+), 3 deletions(-) Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> --- qemu/vnc.c | 29 ++++++++++++++++++++++++++--- 1 files changed, 26 insertions(+), 3 deletions(-) diff --git a/qemu/vnc.c b/qemu/vnc.c index e72609d..160fd49 100644 --- a/qemu/vnc.c +++ b/qemu/vnc.c @@ -1173,6 +1173,27 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym) } } + if ((sym >= 'A' && sym <= 'Z') || (sym >= 'a' && sym <= 'z')) { + /* If the capslock state needs to change then simulate an additional + keypress before sending this one. This will happen if the user + toggles capslock away from the VNC window. + */ + int uppercase = !!(sym >= 'A' && sym <= 'Z'); + int shift = !!(vs->modifiers_state[0x2a] | vs->modifiers_state[0x36]); + int capslock = !!(vs->modifiers_state[0x3a]); + if (capslock) { + if (uppercase == shift) { + vs->modifiers_state[0x3a] = 0; + press_key(vs, 0xffe5); + } + } else { + if (uppercase != shift) { + vs->modifiers_state[0x3a] = 1; + press_key(vs, 0xffe5); + } + } + } + if (is_graphic_console()) { if (keycode & 0x80) kbd_put_keycode(0xe0); @@ -1238,11 +1259,13 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym) static void key_event(VncState *vs, int down, uint32_t sym) { int keycode; + int lsym = sym; - if (sym >= 'A' && sym <= 'Z' && is_graphic_console()) - sym = sym - 'A' + 'a'; + if (lsym >= 'A' && lsym <= 'Z' && is_graphic_console()) { + lsym = lsym - 'A' + 'a'; + } - keycode = keysym2scancode(vs->vd->kbd_layout, sym & 0xFFFF); + keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF); do_key_event(vs, down, keycode, sym); } -- 1.6.3.rc4.29.g8146