mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
[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>
This commit is contained in:
1 parent
9f92ded9df
commit
c5b151445d
2 files changed
+100
-8
No files matched your search
@@ -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;
|
||||
}
|
||||
+84
-8
@@ -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);
|
||||
}
|
||||
|
||||
|
||||