[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