]> xenbits.xensource.com Git - qemu-xen-4.1-testing.git/commitdiff
ioemu: fix VNC altgr-insert behavior
authorIan Jackson <ian.jackson@eu.citrix.com>
Tue, 14 Sep 2010 16:31:43 +0000 (17:31 +0100)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Tue, 14 Sep 2010 16:31:43 +0000 (17:31 +0100)
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 <cyliu@novell.com>
keymaps.c
vnc.c

index d591211d32c0964b79b7d37d3faa7d65ba1501c2..a61d46508f748eed9289d65a3d14bd446d8776db 100644 (file)
--- 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 702ee5d912be9ed7d2e4bac533b113acfb1ad7f5..072674688cf3e71635579352a95433b8870f3491 100644 (file)
--- 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.
         */