[Spice-devel] [spice-gtk 1/3] Send Zenkaku_Hankaku key in JP keyboard
Takao Fujiwara
tfujiwar at redhat.com
Tue Apr 12 10:53:34 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 | 87 +++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 86 insertions(+), 2 deletions(-)
diff --git a/src/spice-widget-priv.h b/src/spice-widget-priv.h
index 95bca8a..99c350b 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 win_keyboard_layout;
#endif
guint keypress_delay;
gint zoom_level;
diff --git a/src/spice-widget.c b/src/spice-widget.c
index 6f638fb..4ce1ea2 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
@@ -101,6 +102,9 @@ static guint signals[SPICE_DISPLAY_LAST_SIGNAL];
static HWND win32_window = NULL;
#endif
+#ifdef G_OS_WIN32
+static GdkFilterReturn spice_display_window_filter(GdkXEvent *xev, GdkEvent *event, gpointer data);
+#endif
static void update_keyboard_grab(SpiceDisplay *display);
static void try_keyboard_grab(SpiceDisplay *display);
static void try_keyboard_ungrab(SpiceDisplay *display);
@@ -429,6 +433,9 @@ static void spice_display_finalize(GObject *obj)
{
SpiceDisplay *display = SPICE_DISPLAY(obj);
SpiceDisplayPrivate *d = display->priv;
+#ifdef G_OS_WIN32
+ GdkWindow *window = NULL;
+#endif
SPICE_DEBUG("Finalize spice display");
@@ -439,6 +446,11 @@ static void spice_display_finalize(GObject *obj)
g_clear_object(&d->mouse_cursor);
g_clear_object(&d->mouse_pixbuf);
+#ifdef G_OS_WIN32
+ window = GDK_WINDOW(gtk_widget_get_window(GTK_WIDGET(display)));
+ gdk_window_remove_filter(window, spice_display_window_filter, display);
+#endif
+
G_OBJECT_CLASS(spice_display_parent_class)->finalize(obj);
}
@@ -582,6 +594,9 @@ static void spice_display_init(SpiceDisplay *display)
GtkWidget *area;
SpiceDisplayPrivate *d;
GtkTargetEntry targets = { "text/uri-list", 0, 0 };
+#ifdef G_OS_WIN32
+ GdkWindow *window = NULL;
+#endif
d = display->priv = SPICE_DISPLAY_GET_PRIVATE(display);
@@ -629,6 +644,12 @@ 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->win_keyboard_layout = GetKeyboardLayout(0);
+ window = GDK_WINDOW(gtk_widget_get_window(GTK_WIDGET(display)));
+ gdk_window_add_filter(window, spice_display_window_filter, display);
+#endif
}
static GObject *
@@ -742,6 +763,25 @@ static LRESULT CALLBACK keyboard_hook_cb(int code, WPARAM wparam, LPARAM lparam)
}
return CallNextHookEx(NULL, code, wparam, lparam);
}
+
+static GdkFilterReturn spice_display_window_filter(GdkXEvent *xev, GdkEvent *event, gpointer data)
+{
+ MSG *msg = (MSG *)xev;
+ SpiceDisplay *display = (SpiceDisplay *)data;
+ SpiceDisplayPrivate *d;
+
+ g_return_val_if_fail(SPICE_IS_DISPLAY(display), GDK_FILTER_CONTINUE);
+
+ d = display->priv;
+
+ switch (msg->message) {
+ case WM_INPUTLANGCHANGE:
+ d->win_keyboard_layout = (HKL)msg->lParam;
+ break;
+ default:;
+ }
+ return GDK_FILTER_CONTINUE;
+}
#endif
/**
@@ -1400,6 +1440,10 @@ 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;
+ WORD langid = LOWORD(d->win_keyboard_layout);
+#endif
#ifdef G_OS_WIN32
/* on windows, we ought to ignore the reserved key event? */
@@ -1446,9 +1490,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 (langid) {
+ 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