diff options
author | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2007-07-23 10:02:37 +0100 |
---|---|---|
committer | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2007-07-23 10:02:37 +0100 |
commit | c5b151445d21dcbc0bc80b70e4bdfcde789ee3ca (patch) | |
tree | 55baca9b186661cac9aa29de0f856b7e4e939d0c /tools | |
parent | 9f92ded9df56ef4eabeae6550ae4d1fd8b2937d0 (diff) | |
download | xen-c5b151445d21dcbc0bc80b70e4bdfcde789ee3ca.tar.gz xen-c5b151445d21dcbc0bc80b70e4bdfcde789ee3ca.tar.bz2 xen-c5b151445d21dcbc0bc80b70e4bdfcde789ee3ca.zip |
[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>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/ioemu/keymaps.c | 16 | ||||
-rw-r--r-- | tools/ioemu/vnc.c | 92 |
2 files changed, 100 insertions, 8 deletions
diff --git a/tools/ioemu/keymaps.c b/tools/ioemu/keymaps.c index e485739298..b98a52d4ea 100644 --- a/tools/ioemu/keymaps.c +++ b/tools/ioemu/keymaps.c @@ -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_layout(const char *language, 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_layout, int keysym) 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 --git a/tools/ioemu/vnc.c b/tools/ioemu/vnc.c index 524da36cc2..0473042820 100644 --- a/tools/ioemu/vnc.c +++ b/tools/ioemu/vnc.c @@ -915,12 +915,69 @@ static void press_key(VncState *vs, int keysym) 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, int down, uint32_t sym) 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, int down, uint32_t sym) } 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, int down, uint32_t sym) } 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, int down, uint32_t sym) 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); } |