[Spice-devel] [spice-gtk 1/3] Send Zenkaku_Hankaku key in JP keyboard
Frediano Ziglio
fziglio at redhat.com
Mon Apr 11 15:52:10 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
>
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
More information about the Spice-devel
mailing list