> > 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 > I think instead of using an hook would be better to use gdk_window_add_filter. You are registering the hook only when we have the grab so you won't get the message if we don't have the focus. Even better ... > /** > @@ -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; ... here to do WORD langid = LOWORD(GetKeyboardLayout(0)); > +#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)) { 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) { Frediano _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel