[Spice-devel] [spice-gtk 1/3] Send Zenkaku_Hankaku key in JP keyboard

Takao Fujiwara tfujiwar at redhat.com
Wed Apr 6 04:30:09 UTC 2016


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_DBE_DBCSCHAR) 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_DBE_SBCSCHAR) 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_DBE_SBCSCHAR).

VK_CAPITAL, VK_DBE_ROMAN are also applied the similar fixes.
---
 src/spice-widget-priv.h |  1 +
 src/spice-widget.c      | 78
+++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 77 insertions(+), 2 deletions(-)

diff --git a/src/spice-widget-priv.h b/src/spice-widget-priv.h
index 95bca8a..95a8371 100644
--- a/src/spice-widget-priv.h
+++ b/src/spice-widget-priv.h
@@ -117,6 +117,7 @@ struct _SpiceDisplayPrivate {
     gint                    mark;
 #ifdef WIN32
     HHOOK                   keyboard_hook;
+    HHOOK                   call_wnd_proc_hook;
     int                     win_mouse[3];
     int                     win_mouse_speed;
 #endif
diff --git a/src/spice-widget.c b/src/spice-widget.c
index f605439..49e1f2a 100644
--- a/src/spice-widget.c
+++ b/src/spice-widget.c
@@ -30,6 +30,7 @@
 #endif
 #ifdef G_OS_WIN32
 #include <windows.h>
+#include <ime.h>
 #include <gdk/gdkwin32.h>
 #ifndef MAPVK_VK_TO_VSC /* may be undefined in older mingw-headers */
 #define MAPVK_VK_TO_VSC 0
@@ -99,6 +100,7 @@ static guint signals[SPICE_DISPLAY_LAST_SIGNAL];
 
 #ifdef G_OS_WIN32
 static HWND win32_window = NULL;
+static HKL  win32_keymap;
 #endif
 
 static void update_keyboard_grab(SpiceDisplay *display);
@@ -644,6 +646,10 @@ 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
+    win32_keymap = GetKeyboardLayout(0);
+#endif
 }
 
 static GObject *
@@ -757,6 +763,20 @@ static LRESULT CALLBACK keyboard_hook_cb(int code,
WPARAM wparam, LPARAM lparam)
     }
     return CallNextHookEx(NULL, code, wparam, lparam);
 }
+
+static LRESULT CALLBACK call_wnd_proc_hook_cb(int code, WPARAM wparam,
LPARAM lparam)
+{
+    if  (code >= 0) {
+        CWPSTRUCT *cwp = (CWPSTRUCT *) lparam;
+        switch (cwp->message) {
+        case WM_INPUTLANGCHANGE:
+            win32_keymap = (HKL) cwp->lParam;
+            break;
+        default:;
+        }
+    }
+    return CallNextHookEx(NULL, code, wparam, lparam);
+}
 #endif
 
 /**
@@ -813,6 +833,13 @@ static void try_keyboard_grab(SpiceDisplay
*display)
         d->keyboard_hook = SetWindowsHookEx(WH_KEYBOARD_LL,
keyboard_hook_cb,
                                             GetModuleHandle(NULL), 0);
     g_warn_if_fail(d->keyboard_hook != NULL);
+
+    if (d->call_wnd_proc_hook == NULL)
+        d->call_wnd_proc_hook = SetWindowsHookEx(WH_CALLWNDPROC,
+                                                 call_wnd_proc_hook_cb
,
+                                                 GetModuleHandle(NULL)
,
+                                                 GetCurrentThreadId())
;
+    g_warn_if_fail(d->call_wnd_proc_hook != NULL);
 #endif
     status = gdk_keyboard_grab(gtk_widget_get_window(widget), FALSE,
                                GDK_CURRENT_TIME);
@@ -840,6 +867,11 @@ static void try_keyboard_ungrab(SpiceDisplay
*display)
         UnhookWindowsHookEx(d->keyboard_hook);
         d->keyboard_hook = NULL;
     }
+
+    if (d->call_wnd_proc_hook != NULL) {
+        UnhookWindowsHookEx(d->call_wnd_proc_hook);
+        d->call_wnd_proc_hook = NULL;
+    }
 #endif
     d->keyboard_grab_active = false;
     g_signal_emit(widget, signals[SPICE_DISPLAY_KEYBOARD_GRAB], 0,
false);
@@ -1418,6 +1450,9 @@ static gboolean key_event(GtkWidget *widget,
GdkEventKey *key)
     SpiceDisplay *display = SPICE_DISPLAY(widget);
     SpiceDisplayPrivate *d = display->priv;
     int scancode;
+#ifdef G_OS_WIN32
+    int native_scancode;
+#endif
 
 #ifdef G_OS_WIN32
     /* on windows, we ought to ignore the reserved key event? */
@@ -1464,9 +1499,48 @@ 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 virtual-key codes are missed in MapVirtualKey(). */
+    switch (LOWORD(win32_keymap)) {
+    case MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN):
+        if (native_scancode == 0) {
+            switch (key->hardware_keycode) {
+            case VK_DBE_DBCSCHAR:       /* from Pressed
Zenkaku_Hankaku */
+            case VK_KANJI:              /* from Alt + Zenkaku_Hankaku
*/
+            case VK_DBE_ENTERIMECONFIGMODE:
+                                        /* from
Ctrl+Alt+Zenkaku_Hankaku */
+                scancode = MapVirtualKey(VK_DBE_SBCSCHAR,
MAPVK_VK_TO_VSC);
+                                        /* to Released Zenkaku_Hankaku
*/
+                goto got_scancode;
+            case VK_CAPITAL:            /* from Shift + Eisu_toggle */
+            case VK_DBE_CODEINPUT:      /* from Pressed
Ctrl+Alt+Eisu_toggle */
+            case VK_DBE_NOCODEINPUT:    /* from Released
Ctrl+Alt+Eisu_toggle */
+                scancode = MapVirtualKey(VK_DBE_ALPHANUMERIC,
MAPVK_VK_TO_VSC);
+                                        /* to Eisu_toggle */
+                goto got_scancode;
+            case VK_DBE_ROMAN:          /* from Pressed
Alt+Hiragana_Katakana */
+            case VK_KANA:               /* from
Ctrl+Shift+Hiragana_Katakana */
+                scancode = MapVirtualKey(VK_DBE_HIRAGANA,
MAPVK_VK_TO_VSC);
+                                        /* to Hiragana_Katakana */
+                goto got_scancode;
+            case VK_DBE_ENTERWORDREGISTERMODE:
+                                        /* from Ctrl + Alt + Muhenkan
*/
+                scancode = MapVirtualKey(VK_NONCONVERT,
MAPVK_VK_TO_VSC);
+                                        /* to Muhenkan */
+                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


More information about the Spice-devel mailing list