Le 18/12/2014 12:55, Kevin Wolf a écrit :
CCing Stefan Weil, who is both the Windows maintainer and the author of
commit 2777ccc5, which introduced the MapVirtualKey() call. As there is
a special case for Alt Gr in the code, I suppose he had this working
back then.
From what I understand (which isn't much when it's about Windows), it
seems very unlikely to me that the change would break anything that is
working today; but you should probably give it some testing before
posting a patch.
Kevin
I could not find a case where this alt-gr code is actually useful.
From what I tried, MapVirtualKey can only issue 103 value with input
not relevant with alt-gr.
I have attached a set of 3 patchs for review. These are the first I
issue, so please tell if the format is not the one expected.
0001 handles the rhs keystrokes in ui/gtk.c
0002 triggers the ctrl up event in ui/gtk.c
0003 triggers the ctrl up event in ui/sdl2.c
I had preferred to fix directly in ui/input.c in order to fix all UI at
once (including vnc and sdl1, which I cannot run on my host), but this
involves adding some state accessible to ui/input.c. QemuConsole looks
most relevant but is private to ui/console.c.
The fix is successful in a Linux guest.
The fix has no noticeable effect in a Windows guest, precisely because
the guest internally remaps alt-gr to ctrl-alt.
The one caveat I can raise is that the key combination l-ctrl + r-alt
cannot be sent anymore to the guest.
Remi
>From edec88edb24f5ec9abede2f3de7767f294c6cbc1 Mon Sep 17 00:00:00 2001
From: Remi Thebault <remi.theba...@outlook.com>
Date: Sun, 21 Dec 2014 17:15:56 +0100
Subject: [PATCH 1/3] input: gtk win32 ui sends r-ctrl and r-alt key events
gtk ui on win32 only sent left ctrl and alt code, whatever the keystroke.
In case of a right keystroke and left scan code, this commit corrects
the qemu code to fit the actual keystroke.
Signed-off-by: Remi Thebault <remi.theba...@outlook.com>
---
ui/gtk.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/ui/gtk.c b/ui/gtk.c
index 0385757..27696fa 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -901,7 +901,21 @@ static int gd_map_keycode(GtkDisplayState *s, GdkDisplay
*dpy, int gdk_keycode)
#ifdef GDK_WINDOWING_WIN32
if (GDK_IS_WIN32_DISPLAY(dpy)) {
qemu_keycode = MapVirtualKey(gdk_keycode, MAPVK_VK_TO_VSC);
+ /*
+ * MapVirtualKey maps same code for left and right ctrl and alt keys.
+ * Following switch disambiguates the left and right codes.
+ */
switch (qemu_keycode) {
+ case 0x1d: /* L-ctrl */
+ if (gdk_keycode == VK_RCONTROL) {
+ qemu_keycode |= SCANCODE_GREY;
+ }
+ break;
+ case 0x38: /* L-alt */
+ if (gdk_keycode == VK_RMENU) {
+ qemu_keycode |= SCANCODE_GREY;
+ }
+ break;
case 103: /* alt gr */
qemu_keycode = 56 | SCANCODE_GREY;
break;
--
1.8.5.2.msysgit.0
>From d1d3289867263bf3fc42a27e3efb8c5d58c2ee38 Mon Sep 17 00:00:00 2001
From: Remi Thebault <remi.theba...@outlook.com>
Date: Sun, 21 Dec 2014 17:17:11 +0100
Subject: [PATCH 2/3] input: gtk win32 ui handles altgr key correctly
Linux guest / Windows host had a dead altgr key problem due to
Windows mapping of altgr to ctrl-alt. This commit fixes it by sending
a fake ctrl-up event to the guest when appropriate.
In case of turbo mode, only one fake event is sent.
In a windows guest, altgr key still works as usual.
Signed-off-by: Remi Thebault <remi.theba...@outlook.com>
---
ui/gtk.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/ui/gtk.c b/ui/gtk.c
index 27696fa..a6c623c 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -230,6 +230,12 @@ struct GtkDisplayState {
bool modifier_pressed[ARRAY_SIZE(modifier_keycode)];
bool has_evdev;
+
+#if defined(_WIN32)
+ /* win32 alt-gr handling */
+ bool l_ctrl_down;
+ bool r_alt_down;
+#endif
};
static void gd_grab_pointer(VirtualConsole *vc);
@@ -973,6 +979,30 @@ static gboolean gd_key_event(GtkWidget *widget,
GdkEventKey *key, void *opaque)
}
}
+#if defined(_WIN32)
+ /* Windows maps altgr key to l-ctrl + r-alt.
+ For proper handling in the guest, only r-alt is to be sent.
+ This is done by sending a fake "ctrl up" event when appropriate. */
+ switch (qemu_keycode) {
+ case 0x1d: /* l-ctrl */
+ if (!s->l_ctrl_down && s->r_alt_down) {
+ /* fake ctrl up already sent */
+ return TRUE;
+ }
+ s->l_ctrl_down = (key->type == GDK_KEY_PRESS);
+ break;
+ case 0xb8: /* r-alt */
+ if (s->l_ctrl_down && !s->r_alt_down &&
+ key->type == GDK_KEY_PRESS) {
+ /* sending fake "ctrl up" event */
+ qemu_input_event_send_key_number(vc->gfx.dcl.con, 0x1d, FALSE);
+ s->l_ctrl_down = FALSE;
+ }
+ s->r_alt_down = (key->type == GDK_KEY_PRESS);
+ break;
+ }
+#endif
+
qemu_input_event_send_key_number(vc->gfx.dcl.con, qemu_keycode,
key->type == GDK_KEY_PRESS);
--
1.8.5.2.msysgit.0
>From 9f755bea4f305e255e92f901e26f76e7a7364ecb Mon Sep 17 00:00:00 2001
From: Remi Thebault <remi.theba...@outlook.com>
Date: Sun, 21 Dec 2014 17:18:05 +0100
Subject: [PATCH 3/3] input: sdl2 win32 ui handles altgr key correctly
Linux guest / Windows host had a dead altgr key problem due to
Windows mapping of altgr to ctrl-alt. This commit fixes it by sending
a fake ctrl-up event to the guest when appropriate.
In case of turbo mode, only one fake event is sent.
In a windows guest, altgr key still works as usual.
Signed-off-by: Remi Thebault <remi.theba...@outlook.com>
---
ui/sdl2.c | 40 ++++++++++++++++++++++++++++++++++++----
1 file changed, 36 insertions(+), 4 deletions(-)
diff --git a/ui/sdl2.c b/ui/sdl2.c
index 1ad74ba..42ed220 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -73,6 +73,12 @@ static SDL_Cursor *guest_sprite;
static int scaling_active;
static Notifier mouse_mode_notifier;
+#if defined(_WIN32)
+/* win32 alt-gr handling */
+static bool l_ctrl_down = 0;
+static bool r_alt_down = 0;
+#endif
+
static void sdl_update_caption(struct sdl2_state *scon);
static struct sdl2_state *get_scon_from_window(uint32_t window_id)
@@ -252,11 +258,37 @@ static void sdl_process_key(struct sdl2_state *scon,
} else {
modifiers_state[ev->keysym.scancode] = 1;
}
- /* fall though */
- default:
- qemu_input_event_send_key_qcode(con, qcode,
- ev->type == SDL_KEYDOWN);
+ break;
}
+
+#if defined(_WIN32)
+ /* Windows maps altgr key to l-ctrl + r-alt.
+ For proper handling in the guest, only r-alt is to be sent.
+ This is done by sending a fake "ctrl up" event when appropriate. */
+ switch (ev->keysym.scancode) {
+ case SDL_SCANCODE_LCTRL: /* l-ctrl */
+ if (!l_ctrl_down && r_alt_down) {
+ /* fake ctrl up already sent */
+ return;
+ }
+ l_ctrl_down = (ev->type == SDL_KEYDOWN);
+ break;
+ case SDL_SCANCODE_RALT: /* r-alt */
+ if (l_ctrl_down && !r_alt_down &&
+ ev->type == SDL_KEYDOWN) {
+ /* sending fake "ctrl up" event */
+ qemu_input_event_send_key_qcode(con,
+ sdl2_scancode_to_qcode[SDL_SCANCODE_LCTRL],
+ false);
+ l_ctrl_down = false;
+ }
+ r_alt_down = (ev->type == SDL_KEYDOWN);
+ break;
+ }
+#endif
+
+ qemu_input_event_send_key_qcode(con, qcode,
+ ev->type == SDL_KEYDOWN);
}
static void sdl_update_caption(struct sdl2_state *scon)
--
1.8.5.2.msysgit.0