aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>2007-07-23 10:02:37 +0100
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>2007-07-23 10:02:37 +0100
commitc5b151445d21dcbc0bc80b70e4bdfcde789ee3ca (patch)
tree55baca9b186661cac9aa29de0f856b7e4e939d0c /tools
parent9f92ded9df56ef4eabeae6550ae4d1fd8b2937d0 (diff)
downloadxen-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.c16
-rw-r--r--tools/ioemu/vnc.c92
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);
}