Handle JP keyboard with spice-gtk from Windows client

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I noticed Linux GNOME desktop hangs up when Windows virt-viewer connects to the desktop and type some specific keys on JP keyboard.

Server: GNOME desktop and IBus in RHEL 7
Client virt-viewer in Windows 7 with JP 106 keyboard

When I see the key events with 'xev' command in GNOME desktop, I observed the unlimited too many key events of Zenkaku_Hankaku key and it caused the
desktop freeze.
The attached three patches resolves the desktop issues.

1. spice-gtk-1311820-01-zkhk.patch
Zenkaku_Hankaku key has the different virtual-key codes between WM_KEYDOWN and WM_KEYUP and MapVirtualKey() cannot get the scancode from virtual-key
code of WM_KEYDOWN (VK_OEM_ENLW) and spice-gtk didn't send the key press events and caused the desktop freeze with unlimited key release events.

The fix is to get the scancode from virtual-key code of WM_KEYUP (VK_OEM_AUTO) and Zenkaku_Hankaku key works fine.

Alt + Zenkaku_Hankaku key also has the different virtual-key code and MapVirtualKey() cannot get the
scancode from the virtual-key and spice-gtk didn't send the key press events and Alt+Zenkaku_Hankaku could not be used.

The fix is to get the scancode from virtual-key code of Zenkaku_Hankaku key (VK_OEM_AUTO).

VK_CAPITAL, VK_OEM_BACKTAB are also applied the similar fixes.

2. spice-gtk-1311820-02-freeze.patch
After spice-gtk-1311820-01-zkhk.patch is applied, WM_KEYDOWN of Alt+Zenkaku_Hankaku (VK_KANJI) can be sent with spice-gtk but Alt+Zenkaku_Hankaku did
not send the WM_KEYUP event in Windows and it caused Linux desktop freeze with unlimited key press events.

The fix is to send the key release event in spice-gtk.

VK_OEM_ATTN, VK_OEM_COPY, VK_OEM_BACKTAB are applied the similar fixes.

3. spice-gtk-1311820-03-hangul.patch
This is an additional fix. Korean keyboard assigns Hangul key on the position of Right Alt and Left Alt and Hangul keys have the different scancodes
but MapVirtualKey() returned the same scancode and could not use Hangul key on Linux desktop.

The fix is to send the right scancode of VK_HANGUL.

Thanks,
Fujiwara
>From d3e750a254e3ba5fc6332616a49ff9da42f77d46 Mon Sep 17 00:00:00 2001
From: Takao Fujiwara <tfujiwar@xxxxxxxxxx>
Date: Thu, 31 Mar 2016 19:38:07 +0900
Subject: [PATCH] Send Zenkaku_Hankaku key in JP keyboard.

MapVirtualKey() returns the scancode of the released Zenkaku_Hankaku key
but does not pressed one and modifiered one. Any cases should be sent
to use input method engines.
---
 src/spice-widget-priv.h |  1 +
 src/spice-widget.c      | 37 +++++++++++++++++++++++++++++++++++--
 2 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/src/spice-widget-priv.h b/src/spice-widget-priv.h
index 95bca8a..05f6a90 100644
--- a/src/spice-widget-priv.h
+++ b/src/spice-widget-priv.h
@@ -119,6 +119,7 @@ struct _SpiceDisplayPrivate {
     HHOOK                   keyboard_hook;
     int                     win_mouse[3];
     int                     win_mouse_speed;
+    HKL                     keyboard_layout;
 #endif
     guint                   keypress_delay;
     gint                    zoom_level;
diff --git a/src/spice-widget.c b/src/spice-widget.c
index f605439..4e026f3 100644
--- a/src/spice-widget.c
+++ b/src/spice-widget.c
@@ -644,6 +644,9 @@ static void spice_display_init(SpiceDisplay *display)
     d->grabseq = spice_grab_sequence_new_from_string("Control_L+Alt_L");
     d->activeseq = g_new0(gboolean, d->grabseq->nkeysyms);
     d->mouse_cursor = get_blank_cursor();
+#ifdef G_OS_WIN32
+    d->keyboard_layout = GetKeyboardLayout(0);
+#endif
 }
 
 static GObject *
@@ -1418,6 +1421,7 @@ static gboolean key_event(GtkWidget *widget, GdkEventKey *key)
     SpiceDisplay *display = SPICE_DISPLAY(widget);
     SpiceDisplayPrivate *d = display->priv;
     int scancode;
+    int native_scancode;
 
 #ifdef G_OS_WIN32
     /* on windows, we ought to ignore the reserved key event? */
@@ -1464,9 +1468,38 @@ static gboolean key_event(GtkWidget *widget, GdkEventKey *key)
     scancode = vnc_display_keymap_gdk2xtkbd(d->keycode_map, d->keycode_maplen,
                                             key->hardware_keycode);
 #ifdef G_OS_WIN32
+    native_scancode = MapVirtualKey(key->hardware_keycode, MAPVK_VK_TO_VSC);
+
+    /* Some OEM virtual-key codes are missed in MapVirtualKey(). */
+    switch (HIWORD(d->keyboard_layout)) {
+    case 0x411:                         /* JP keyboard */
+        if (native_scancode == 0) {
+            switch (key->hardware_keycode) {
+            case VK_OEM_ENLW:           /* from Pressed Zenkaku_Hankaku */
+            case VK_KANJI:              /* from Alt + Zenkaku_Hankaku */
+                scancode = MapVirtualKey(VK_OEM_AUTO, MAPVK_VK_TO_VSC);
+                                        /* to Released Zenkaku_Hankaku */
+                goto got_scancode;
+            case VK_CAPITAL:            /* from Alt + Eisu_toggle */
+                scancode = MapVirtualKey(VK_OEM_ATTN, MAPVK_VK_TO_VSC);
+                                        /* to Eisu_toggle */
+                goto got_scancode;
+            case VK_OEM_BACKTAB:        /* from Alt + Hiragana_Katakana */
+                scancode = MapVirtualKey(VK_OEM_COPY, MAPVK_VK_TO_VSC);
+                                        /* to Hiragana_Katakana */
+                goto got_scancode;
+            default:;
+            }
+        }
+        break;
+    default:;
+    }
+
     /* MapVirtualKey doesn't return scancode with needed higher byte */
-    scancode = MapVirtualKey(key->hardware_keycode, MAPVK_VK_TO_VSC) |
-        (scancode & 0xff00);
+    scancode = native_scancode | (scancode & 0xff00);
+
+got_scancode:
+
 #endif
 
     switch (key->type) {
-- 
2.5.0

>From e58345f9c3744dabb4316cffd3707d1534aacaf5 Mon Sep 17 00:00:00 2001
From: Takao Fujiwara <tfujiwar@xxxxxxxxxx>
Date: Thu, 31 Mar 2016 19:42:02 +0900
Subject: [PATCH] Send key release event for some keys in JP keyboard.

Some of the keys in JP keyboard do no send WM_KEYUP and it causes
unlimited key events on Linux desktop. This sends the virtual
key release events to avoid the desktop hangup.
---
 src/spice-widget.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/src/spice-widget.c b/src/spice-widget.c
index 4e026f3..5e71d1b 100644
--- a/src/spice-widget.c
+++ b/src/spice-widget.c
@@ -1422,6 +1422,7 @@ static gboolean key_event(GtkWidget *widget, GdkEventKey *key)
     SpiceDisplayPrivate *d = display->priv;
     int scancode;
     int native_scancode;
+    gboolean no_key_release = FALSE;
 
 #ifdef G_OS_WIN32
     /* on windows, we ought to ignore the reserved key event? */
@@ -1500,11 +1501,28 @@ static gboolean key_event(GtkWidget *widget, GdkEventKey *key)
 
 got_scancode:
 
+    /* Some keys do not send WM_KEYUP */
+    switch (HIWORD(d->keyboard_layout)) {
+    case 0x411:                         /* JP keyboard */
+        switch (key->hardware_keycode) {
+        case VK_KANJI:                  /* Alt + Zenkaku_Hankaku */
+        case VK_OEM_ATTN:               /* Eisu_toggle */
+        case VK_OEM_COPY:               /* Hiragana_Katakana */
+        case VK_OEM_BACKTAB:            /* Alt + Hiragana_Katakana */
+            no_key_release = TRUE;
+            break;
+        default:;
+        }
+        break;
+    default:;
+    }
 #endif
 
     switch (key->type) {
     case GDK_KEY_PRESS:
         send_key(display, scancode, SEND_KEY_PRESS, !key->is_modifier);
+        if (no_key_release)
+            send_key(display, scancode, SEND_KEY_RELEASE, !key->is_modifier);
         break;
     case GDK_KEY_RELEASE:
         send_key(display, scancode, SEND_KEY_RELEASE, !key->is_modifier);
-- 
2.5.0

>From 5742f3057dbac181190d71796906d897fcd1f2c4 Mon Sep 17 00:00:00 2001
From: Takao Fujiwara <tfujiwar@xxxxxxxxxx>
Date: Thu, 31 Mar 2016 19:43:49 +0900
Subject: [PATCH] Send key release event for some keys in JP keyboard.

Some of the keys in JP keyboard do no send WM_KEYUP and it causes
unlimited key events on Linux desktop. This sends the virtual
key release events to avoid the desktop hangup.
---
 src/spice-widget.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/src/spice-widget.c b/src/spice-widget.c
index 5e71d1b..c5a4530 100644
--- a/src/spice-widget.c
+++ b/src/spice-widget.c
@@ -1493,6 +1493,15 @@ static gboolean key_event(GtkWidget *widget, GdkEventKey *key)
             }
         }
         break;
+    case 0x412:                         /* KR keyboard */
+        if (key->hardware_keycode == VK_HANGUL && native_scancode == 0x38) {
+            /* Left Alt (VK_MENU) has the scancode 0x38 but Hangul (VK_HANGUL)
+             * has the scancode 0x138
+             */
+            scancode = native_scancode | 0x100;
+            goto got_scancode;
+        }
+        break;
     default:;
     }
 
-- 
2.5.0

_______________________________________________
Spice-devel mailing list
Spice-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/spice-devel

[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]     [Monitors]