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 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel