ia64/xen-unstable

changeset 15641:c64f2a0dc2d7

[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@jp.fujitsu.com>
author kfraser@localhost.localdomain
date Mon Jul 23 10:02:37 2007 +0100 (2007-07-23)
parents f45c9f122e0e
children 7bdc9f6407d3
files tools/ioemu/keymaps.c tools/ioemu/vnc.c
line diff
     1.1 --- a/tools/ioemu/keymaps.c	Mon Jul 23 09:56:49 2007 +0100
     1.2 +++ b/tools/ioemu/keymaps.c	Mon Jul 23 10:02:37 2007 +0100
     1.3 @@ -49,6 +49,7 @@ typedef struct {
     1.4      int extra_count;
     1.5      struct key_range *keypad_range;
     1.6      struct key_range *numlock_range;
     1.7 +    struct key_range *shift_range;
     1.8  } kbd_layout_t;
     1.9  
    1.10  static void add_to_key_range(struct key_range **krp, int code) {
    1.11 @@ -127,6 +128,10 @@ static kbd_layout_t *parse_keyboard_layo
    1.12  			add_to_key_range(&k->numlock_range, keysym);
    1.13  			fprintf(stderr, "keypad keysym %04x keycode %d\n", keysym, keycode);
    1.14  		    }
    1.15 +		    if (rest && strstr(rest, "shift")) {
    1.16 +			add_to_key_range(&k->shift_range, keysym);
    1.17 +			fprintf(stderr, "shift keysym %04x keycode %d\n", keysym, keycode);
    1.18 +		    }
    1.19  
    1.20  		    /* if(keycode&0x80)
    1.21  		       keycode=(keycode<<8)^0x80e0; */
    1.22 @@ -205,3 +210,14 @@ static int keysymIsNumlock(void *kbd_lay
    1.23  	    return 1;
    1.24      return 0;
    1.25  }
    1.26 +
    1.27 +static int keysymIsShift(void *kbd_layout, int keysym)
    1.28 +{
    1.29 +    kbd_layout_t *k = kbd_layout;
    1.30 +    struct key_range *kr;
    1.31 +
    1.32 +    for (kr = k->shift_range; kr; kr = kr->next)
    1.33 +	if (keysym >= kr->start && keysym <= kr->end)
    1.34 +	    return 1;
    1.35 +    return 0;
    1.36 +}
     2.1 --- a/tools/ioemu/vnc.c	Mon Jul 23 09:56:49 2007 +0100
     2.2 +++ b/tools/ioemu/vnc.c	Mon Jul 23 10:02:37 2007 +0100
     2.3 @@ -915,12 +915,69 @@ static void press_key(VncState *vs, int 
     2.4      kbd_put_keycode(keysym2scancode(vs->kbd_layout, keysym) | 0x80);
     2.5  }
     2.6  
     2.7 +static void press_key_shift_down(VncState *vs, int down, int keycode)
     2.8 +{
     2.9 +    if (down)
    2.10 +        kbd_put_keycode(0x2a & 0x7f);
    2.11 +
    2.12 +    if (keycode & 0x80)
    2.13 +        kbd_put_keycode(0xe0);
    2.14 +    if (down)
    2.15 +        kbd_put_keycode(keycode & 0x7f);
    2.16 +    else
    2.17 +        kbd_put_keycode(keycode | 0x80);
    2.18 +
    2.19 +    if (!down)
    2.20 +        kbd_put_keycode(0x2a | 0x80);
    2.21 +}
    2.22 +
    2.23 +static void press_key_shift_up(VncState *vs, int down, int keycode)
    2.24 +{
    2.25 +    if (down) {
    2.26 +        if (vs->modifiers_state[0x2a])
    2.27 +            kbd_put_keycode(0x2a | 0x80);
    2.28 +        if (vs->modifiers_state[0x36]) 
    2.29 +            kbd_put_keycode(0x36 | 0x80);
    2.30 +    }
    2.31 +
    2.32 +    if (keycode & 0x80)
    2.33 +        kbd_put_keycode(0xe0);
    2.34 +    if (down)
    2.35 +        kbd_put_keycode(keycode & 0x7f);
    2.36 +    else
    2.37 +        kbd_put_keycode(keycode | 0x80);
    2.38 +
    2.39 +    if (!down) {
    2.40 +        if (vs->modifiers_state[0x2a])
    2.41 +            kbd_put_keycode(0x2a & 0x7f);
    2.42 +        if (vs->modifiers_state[0x36]) 
    2.43 +            kbd_put_keycode(0x36 & 0x7f);
    2.44 +    }
    2.45 +}
    2.46 +
    2.47  static void do_key_event(VncState *vs, int down, uint32_t sym)
    2.48  {
    2.49      int keycode;
    2.50 +    int shift_keys = 0;
    2.51 +    int shift = 0;
    2.52 +
    2.53 +    if (is_graphic_console()) {
    2.54 +        if (sym >= 'A' && sym <= 'Z') {
    2.55 +            sym = sym - 'A' + 'a';
    2.56 +            shift = 1;
    2.57 +        }
    2.58 +        else {
    2.59 +            shift = keysymIsShift(vs->kbd_layout, sym & 0xFFFF);
    2.60 +        }
    2.61 +    }
    2.62 +    shift_keys = vs->modifiers_state[0x2a] | vs->modifiers_state[0x36];
    2.63  
    2.64      keycode = keysym2scancode(vs->kbd_layout, sym & 0xFFFF);
    2.65 -    
    2.66 +    if (keycode == 0) {
    2.67 +        fprintf(stderr, "Key lost : keysym=0x%x(%d)\n", sym, sym);
    2.68 +        return;
    2.69 +    }
    2.70 +
    2.71      /* QEMU console switch */
    2.72      switch(keycode) {
    2.73      case 0x2a:                          /* Left Shift */
    2.74 @@ -929,11 +986,15 @@ static void do_key_event(VncState *vs, i
    2.75      case 0x9d:                          /* Right CTRL */
    2.76      case 0x38:                          /* Left ALT */
    2.77      case 0xb8:                          /* Right ALT */
    2.78 -        if (down)
    2.79 +        if (down) {
    2.80              vs->modifiers_state[keycode] = 1;
    2.81 -        else
    2.82 +            kbd_put_keycode(keycode & 0x7f);
    2.83 +        }
    2.84 +        else {
    2.85              vs->modifiers_state[keycode] = 0;
    2.86 -        break;
    2.87 +            kbd_put_keycode(keycode | 0x80);
    2.88 +        }
    2.89 +        return;
    2.90      case 0x02 ... 0x0a: /* '1' to '9' keys */ 
    2.91          if (down && vs->modifiers_state[0x1d] && vs->modifiers_state[0x38]) {
    2.92              /* Reset the modifiers sent to the current console */
    2.93 @@ -943,9 +1004,14 @@ static void do_key_event(VncState *vs, i
    2.94          }
    2.95          break;
    2.96      case 0x45:			/* NumLock */
    2.97 -	if (!down)
    2.98 +	if (down) {
    2.99 +            kbd_put_keycode(keycode & 0x7f);
   2.100 +        }
   2.101 +        else {	
   2.102  	    vs->modifiers_state[keycode] ^= 1;
   2.103 -	break;
   2.104 +            kbd_put_keycode(keycode | 0x80);
   2.105 +        }
   2.106 +	return;
   2.107      }
   2.108  
   2.109      if (keycodeIsKeypad(vs->kbd_layout, keycode)) {
   2.110 @@ -967,6 +1033,18 @@ static void do_key_event(VncState *vs, i
   2.111      }
   2.112  
   2.113      if (is_graphic_console()) {
   2.114 +        /*  If the shift state needs to change then simulate an additional
   2.115 +            keypress before sending this one.
   2.116 +        */
   2.117 +        if (shift && !shift_keys) {
   2.118 +            press_key_shift_down(vs, down, keycode);
   2.119 +            return;
   2.120 +        }
   2.121 +        else if (!shift && shift_keys) {
   2.122 +            press_key_shift_up(vs, down, keycode);
   2.123 +            return;
   2.124 +        }
   2.125 +
   2.126          if (keycode & 0x80)
   2.127              kbd_put_keycode(0xe0);
   2.128          if (down)
   2.129 @@ -1021,8 +1099,6 @@ static void do_key_event(VncState *vs, i
   2.130  
   2.131  static void key_event(VncState *vs, int down, uint32_t sym)
   2.132  {
   2.133 -    if (sym >= 'A' && sym <= 'Z' && is_graphic_console())
   2.134 -	sym = sym - 'A' + 'a';
   2.135      do_key_event(vs, down, sym);
   2.136  }
   2.137