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

Reply via email to