# HG changeset patch # User Ian Jackson # Date 1284481903 -3600 # Node ID f71a4c18e34e86e1011662fa42c10ec54bff0688 # Parent 080b5a094d4e0acab6646125f91f988911409016 ioemu: fix VNC altgr-insert behavior When access to a Xen DomU (Linux) from a VNC client in Windows, alt-gr key is not working properly with Spanish keyboard. When Alt + another key pressed, vncserver receives Altgr down, Altgr up and key down messages in order, that causes incorrect output. With following patch, when vncerver receives key down message, it first check if the keysym needs altgr modifer, if it needs altgr modifier but altgr is not 'down', sending altgr keycode before sending key keycode. Signed-off-by: Chunyan Liu committer: Ian Jackson git-commit-id: f95d202ed6444dacb15fbea4dee185eb0e048d9a diff -r 080b5a094d4e -r f71a4c18e34e keymaps.c --- a/tools/ioemu-qemu-xen/keymaps.c Wed Sep 08 16:38:09 2010 +0100 +++ b//tools/ioemu-qemu-xen/keymaps.c Tue Sep 14 17:31:43 2010 +0100 @@ -51,6 +51,7 @@ struct key_range *numlock_range; struct key_range *shift_range; struct key_range *localstate_range; + struct key_range *altgr_range; } kbd_layout_t; static void add_to_key_range(struct key_range **krp, int code) { @@ -133,7 +134,11 @@ add_to_key_range(&k->localstate_range, keycode); //fprintf(stderr, "localstate keysym %04x keycode %d\n", keysym, keycode); } - + if (rest && strstr(rest, "altgr")) { + add_to_key_range(&k->altgr_range, keysym); + //fprintf(stderr, "altgr keysym %04x keycode %d\n", keysym, keycode); + } + /* if(keycode&0x80) keycode=(keycode<<8)^0x80e0; */ if (keysym < MAX_NORMAL_KEYCODE) { @@ -233,3 +238,16 @@ return 0; return 1; } + +static inline int keysym_is_altgr(void *kbd_layout, int keysym) +{ + kbd_layout_t *k = kbd_layout; + struct key_range *kr; + + for (kr = k->altgr_range; kr; kr = kr->next) + if (keysym >= kr->start && keysym <= kr->end){ + return 1; + } + return 0; +} + diff -r 080b5a094d4e -r f71a4c18e34e vnc.c --- a/tools/ioemu-qemu-xen/vnc.c Wed Sep 08 16:38:09 2010 +0100 +++ b/tools/ioemu-qemu-xen/vnc.c Tue Sep 14 17:31:43 2010 +0100 @@ -1274,12 +1274,27 @@ } } +static void press_key_altgr_down(VncState *vs, int down) +{ + kbd_put_keycode(0xe0); + if (down){ + kbd_put_keycode(0xb8 & 0x7f); + vs->modifiers_state[0xb8] = 1; + } + else { + kbd_put_keycode(0xb8 | 0x80); + vs->modifiers_state[0xb8] = 0; + } +} + static void do_key_event(VncState *vs, int down, uint32_t sym) { int keycode; int shift_keys = 0; int shift = 0; int keypad = 0; + int altgr = 0; + int altgr_keys = 0; if (is_graphic_console()) { if (sym >= 'A' && sym <= 'Z') { @@ -1289,8 +1304,11 @@ else { shift = keysym_is_shift(vs->kbd_layout, sym & 0xFFFF); } + + altgr = keysym_is_altgr(vs->kbd_layout, sym & 0xFFFF); } shift_keys = vs->modifiers_state[0x2a] | vs->modifiers_state[0x36]; + altgr_keys = vs->modifiers_state[0xb8]; keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF); if (keycode == 0) { @@ -1357,6 +1375,11 @@ } if (is_graphic_console()) { + + if (altgr && !altgr_keys) { + press_key_altgr_down(vs, down); + } + /* If the shift state needs to change then simulate an additional keypress before sending this one. Ignore for non shiftable keys. */