[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] [IOEMU] Fix shift key for graphical vnc display



# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1185181357 -3600
# Node ID c64f2a0dc2d721734f5058d7bbfe9e900522c277
# Parent  f45c9f122e0eabf80d8f5e908a6bdc08a5810cc3
[IOEMU] Fix shift key for graphical vnc display

There is a problem in the input of the key in the VNC connection on
the HVM domain. When client's keyboard is not the same as the kind of
the keyboard of qemu-dm and GuestOS, it is not possible to input it
correctly.

   VNC client     qemu-dm & GuestOS
--------------+-----------------------
    ja             en-us               ==> NG
    en-us          en-us               ==> OK

Originally, the same keysym-code between client and qemu-dm is
transmitted. However, even if it is the same character, the state of
shift is different according to the kind of keyboard.

ex.
   "=" charactor
---------------------
en-us :  "="
ja    :  shift + "-"

Therefore, it is necessary to handle the state of the shift by setting
qemu-dm and GuestOS. There is information on whether shift is
necessary for each key for the keymap of qemu-dm.

ex.
 VNC client        : ja
 qemu-dm & GuestOS : en-us
 input key         : "="
 event client to qemu-dm :
  shift(push) >> "="(push) >> "="(release) >> shift(release)
 event qemu-dm to guest :
  shift(push) >> shift(release) >> "="(push) >> "="(release) >>
 shift(push) >>
shift(release)

This patch handled the state of shift from the set keymap.
When client's keyboard is not same as the kind of qemu-dm/GuestOS,
it is possible to input it correctly.
It was confirmed to input it correctly mutually with this patch
between en-us and ja.

Signed-off-by: Takanori Kasai <kasai.takanori@xxxxxxxxxxxxxx>
---
 tools/ioemu/keymaps.c |   16 ++++++++
 tools/ioemu/vnc.c     |   92 +++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 100 insertions(+), 8 deletions(-)

diff -r f45c9f122e0e -r c64f2a0dc2d7 tools/ioemu/keymaps.c
--- a/tools/ioemu/keymaps.c     Mon Jul 23 09:56:49 2007 +0100
+++ b/tools/ioemu/keymaps.c     Mon Jul 23 10:02:37 2007 +0100
@@ -49,6 +49,7 @@ typedef struct {
     int extra_count;
     struct key_range *keypad_range;
     struct key_range *numlock_range;
+    struct key_range *shift_range;
 } kbd_layout_t;
 
 static void add_to_key_range(struct key_range **krp, int code) {
@@ -127,6 +128,10 @@ static kbd_layout_t *parse_keyboard_layo
                        add_to_key_range(&k->numlock_range, keysym);
                        fprintf(stderr, "keypad keysym %04x keycode %d\n", 
keysym, keycode);
                    }
+                   if (rest && strstr(rest, "shift")) {
+                       add_to_key_range(&k->shift_range, keysym);
+                       fprintf(stderr, "shift keysym %04x keycode %d\n", 
keysym, keycode);
+                   }
 
                    /* if(keycode&0x80)
                       keycode=(keycode<<8)^0x80e0; */
@@ -205,3 +210,14 @@ static int keysymIsNumlock(void *kbd_lay
            return 1;
     return 0;
 }
+
+static int keysymIsShift(void *kbd_layout, int keysym)
+{
+    kbd_layout_t *k = kbd_layout;
+    struct key_range *kr;
+
+    for (kr = k->shift_range; kr; kr = kr->next)
+       if (keysym >= kr->start && keysym <= kr->end)
+           return 1;
+    return 0;
+}
diff -r f45c9f122e0e -r c64f2a0dc2d7 tools/ioemu/vnc.c
--- a/tools/ioemu/vnc.c Mon Jul 23 09:56:49 2007 +0100
+++ b/tools/ioemu/vnc.c Mon Jul 23 10:02:37 2007 +0100
@@ -915,12 +915,69 @@ static void press_key(VncState *vs, int 
     kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) | 0x80);
 }
 
+static void press_key_shift_down(VncState *vs, int down, int keycode)
+{
+    if (down)
+        kbd_put_keycode(0x2a & 0x7f);
+
+    if (keycode & 0x80)
+        kbd_put_keycode(0xe0);
+    if (down)
+        kbd_put_keycode(keycode & 0x7f);
+    else
+        kbd_put_keycode(keycode | 0x80);
+
+    if (!down)
+        kbd_put_keycode(0x2a | 0x80);
+}
+
+static void press_key_shift_up(VncState *vs, int down, int keycode)
+{
+    if (down) {
+        if (vs->modifiers_state[0x2a])
+            kbd_put_keycode(0x2a | 0x80);
+        if (vs->modifiers_state[0x36]) 
+            kbd_put_keycode(0x36 | 0x80);
+    }
+
+    if (keycode & 0x80)
+        kbd_put_keycode(0xe0);
+    if (down)
+        kbd_put_keycode(keycode & 0x7f);
+    else
+        kbd_put_keycode(keycode | 0x80);
+
+    if (!down) {
+        if (vs->modifiers_state[0x2a])
+            kbd_put_keycode(0x2a & 0x7f);
+        if (vs->modifiers_state[0x36]) 
+            kbd_put_keycode(0x36 & 0x7f);
+    }
+}
+
 static void do_key_event(VncState *vs, int down, uint32_t sym)
 {
     int keycode;
+    int shift_keys = 0;
+    int shift = 0;
+
+    if (is_graphic_console()) {
+        if (sym >= 'A' && sym <= 'Z') {
+            sym = sym - 'A' + 'a';
+            shift = 1;
+        }
+        else {
+            shift = keysymIsShift(vs->kbd_layout, sym & 0xFFFF);
+        }
+    }
+    shift_keys = vs->modifiers_state[0x2a] | vs->modifiers_state[0x36];
 
     keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
-    
+    if (keycode == 0) {
+        fprintf(stderr, "Key lost : keysym=0x%x(%d)\n", sym, sym);
+        return;
+    }
+
     /* QEMU console switch */
     switch(keycode) {
     case 0x2a:                          /* Left Shift */
@@ -929,11 +986,15 @@ static void do_key_event(VncState *vs, i
     case 0x9d:                          /* Right CTRL */
     case 0x38:                          /* Left ALT */
     case 0xb8:                          /* Right ALT */
-        if (down)
+        if (down) {
             vs->modifiers_state[keycode] = 1;
-        else
+            kbd_put_keycode(keycode & 0x7f);
+        }
+        else {
             vs->modifiers_state[keycode] = 0;
-        break;
+            kbd_put_keycode(keycode | 0x80);
+        }
+        return;
     case 0x02 ... 0x0a: /* '1' to '9' keys */ 
         if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
             /* Reset the modifiers sent to the current console */
@@ -943,9 +1004,14 @@ static void do_key_event(VncState *vs, i
         }
         break;
     case 0x45:                 /* NumLock */
-       if (!down)
+       if (down) {
+            kbd_put_keycode(keycode & 0x7f);
+        }
+        else { 
            vs->modifiers_state[keycode] ^= 1;
-       break;
+            kbd_put_keycode(keycode | 0x80);
+        }
+       return;
     }
 
     if (keycodeIsKeypad(vs->kbd_layout, keycode)) {
@@ -967,6 +1033,18 @@ static void do_key_event(VncState *vs, i
     }
 
     if (is_graphic_console()) {
+        /*  If the shift state needs to change then simulate an additional
+            keypress before sending this one.
+        */
+        if (shift && !shift_keys) {
+            press_key_shift_down(vs, down, keycode);
+            return;
+        }
+        else if (!shift && shift_keys) {
+            press_key_shift_up(vs, down, keycode);
+            return;
+        }
+
         if (keycode & 0x80)
             kbd_put_keycode(0xe0);
         if (down)
@@ -1021,8 +1099,6 @@ static void do_key_event(VncState *vs, i
 
 static void key_event(VncState *vs, int down, uint32_t sym)
 {
-    if (sym >= 'A' && sym <= 'Z' && is_graphic_console())
-       sym = sym - 'A' + 'a';
     do_key_event(vs, down, sym);
 }
 

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.