From f95d202ed6444dacb15fbea4dee185eb0e048d9a Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 14 Sep 2010 17:31:43 +0100 Subject: [PATCH] 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 --- keymaps.c | 20 +++++++++++++++++++- vnc.c | 23 +++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/keymaps.c b/keymaps.c index d591211d3..a61d46508 100644 --- a/keymaps.c +++ b/keymaps.c @@ -51,6 +51,7 @@ typedef struct { 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 @@ static kbd_layout_t *parse_keyboard_layout(const char *language, 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 @@ static inline int keycode_is_shiftable(void *kbd_layout, int keycode) 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 --git a/vnc.c b/vnc.c index 702ee5d91..072674688 100644 --- a/vnc.c +++ b/vnc.c @@ -1274,12 +1274,27 @@ static void press_key_shift_up(VncState *vs, int down, int keycode) } } +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 @@ static void do_key_event(VncState *vs, int down, uint32_t sym) 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 @@ static void do_key_event(VncState *vs, int down, uint32_t sym) } 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. */ -- 2.39.5