diff mbox

[v2] alt-gr on Windows

Message ID BLU437-SMTP458BCCBC1E4ECEB68314DBF6340@phx.gbl
State New
Headers show

Commit Message

Thebault, Remi Jan. 25, 2015, 4:36 p.m. UTC
Hello

attached is the v2 set of patchs.

Le 01/01/2015 20:10, Stefan Weil a écrit :
> I suggest calling MapVirtualKey only for those keys which don't need special handling, so it would be in the default case of the switch statement.
Done (patch 0001) . updated code yields to same result as previous patch. Added a FIXME note regarding the previous alt gr fix, which do not look relevant anymore to me.

> It looks like Alt-Ctrl is a valid alternative for pressing AltGr on Windows, so we have to take that into account, too.
Few tests I did on a XP vm give correct keyboard behaviour. looks like this is transparent on Windows guest.

> Wine also needs special handling because it sends a single (different) key code instead of two key codes.
By this I understand that Wine should just be excluded from this fix (what I do by patch 0002)

Regards,
Rémi
From 3ecdd74fd12f33b6c00b66fce2e082c7fe9b273e Mon Sep 17 00:00:00 2001
From: Remi Thebault <remi.thebault@outlook.com>
Date: Sun, 25 Jan 2015 16:57:45 +0100
Subject: [PATCH 1/4 v2] 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.thebault@outlook.com>
---
 ui/gtk.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

--
1.8.5.2.msysgit.0
From b4866d32436e9b6bd9a9488eb5f998d196980e77 Mon Sep 17 00:00:00 2001
From: Remi Thebault <remi.thebault@outlook.com>
Date: Sun, 25 Jan 2015 17:04:01 +0100
Subject: [PATCH 2/4 v2] input: introduce INPUT_NEEDS_ALTGR_FIX macro

Common macro amoung all ui, to provide consistent alt gr fix.
defined such as to have the fix on win32 (excluding wine)
---
 include/ui/input.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/include/ui/input.h b/include/ui/input.h
index 5d5ac00..64e531c 100644
--- a/include/ui/input.h
+++ b/include/ui/input.h
@@ -10,6 +10,13 @@

 #define INPUT_EVENT_ABS_SIZE   0x8000

+#ifndef INPUT_NEEDS_ALTGR_FIX
+# if defined(_WIN32) && !defined(__WINE__)
+#  define INPUT_NEEDS_ALTGR_FIX 1
+# endif
+#endif
+
+
 typedef struct QemuInputHandler QemuInputHandler;
 typedef struct QemuInputHandlerState QemuInputHandlerState;

--
1.8.5.2.msysgit.0
From 23b3b8bfa8dfce05b72bde6a82adf6e122a5d74f Mon Sep 17 00:00:00 2001
From: Remi Thebault <remi.thebault@outlook.com>
Date: Sun, 25 Jan 2015 17:06:11 +0100
Subject: [PATCH 3/4 v2] 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.thebault@outlook.com>
---
 ui/gtk.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/ui/gtk.c b/ui/gtk.c
index da593f7..1287409 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(INPUT_NEEDS_ALTGR_FIX)
+    /* win32 alt-gr handling */
+    bool l_ctrl_down;
+    bool r_alt_down;
+#endif
 };

 static void gd_grab_pointer(VirtualConsole *vc);
@@ -975,6 +981,30 @@ static gboolean gd_key_event(GtkWidget *widget, GdkEventKey *key, void *opaque)
         }
     }

+#if defined(INPUT_NEEDS_ALTGR_FIX)
+    /* 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 8d685ff821480aabf28973d2f174f47921617c01 Mon Sep 17 00:00:00 2001
From: Remi Thebault <remi.thebault@outlook.com>
Date: Sun, 25 Jan 2015 17:09:58 +0100
Subject: [PATCH 4/4 v2] 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.thebault@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..bba8f4f 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(INPUT_NEEDS_ALTGR_FIX)
+/* 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(INPUT_NEEDS_ALTGR_FIX)
+    /* 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
diff mbox

Patch

diff --git a/ui/gtk.c b/ui/gtk.c
index 0385757..da593f7 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -900,10 +900,26 @@  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);
-        switch (qemu_keycode) {
-        case 103:   /* alt gr */
-            qemu_keycode = 56 | SCANCODE_GREY;
+        /*
+           testing for right ctrl and right alt and give corresponding code.
+           for all other keystrokes, scan code is given by MapVirtualKey.
+           (MapVirtualKey maps same code for left and right ctrl and alt keys)
+         */
+        switch (gdk_keycode) {
+        case 0xa3: // r-ctrl
+            qemu_keycode = 0x9d;
+            break;
+        case 0xa5: // r-alt
+            qemu_keycode = 0xb8;
+            break;
+        default:
+            qemu_keycode = MapVirtualKey(gdk_keycode, MAPVK_VK_TO_VSC);
+            /* FIXME: is following check still needed? */
+            switch (qemu_keycode) {
+                case 103:  /* alt gr */
+                qemu_keycode = 56 | SCANCODE_GREY;
+                break;
+            }
             break;
         }
         return qemu_keycode;