diff options
author | Volker RĂ¼melin <vr_qemu@t-online.de> | 2020-05-16 09:20:04 +0200 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2020-05-19 09:06:44 +0200 |
commit | 2df9f5718df7722924699a3754f99165e2f4ae35 (patch) | |
tree | c170cfdabe16d48cee73228963f97d4169e986dd /ui | |
parent | debe78ce14bf8f8940c2bdf3ef387505e9e035a9 (diff) | |
download | qemu-2df9f5718df7722924699a3754f99165e2f4ae35.zip qemu-2df9f5718df7722924699a3754f99165e2f4ae35.tar.gz qemu-2df9f5718df7722924699a3754f99165e2f4ae35.tar.bz2 |
ui/win32-kbd-hook: handle AltGr in a hook procedure
Import win32 keyboard hooking code from project spice-gtk. This
patch removes the extra left control key up/down input events
inserted by Windows for the right alt key up/down input events
with international keyboard layouts. Additionally there's some
code to grab the keyboard.
The next patches will use this code.
Only Windows needs this.
Signed-off-by: Volker RĂ¼melin <vr_qemu@t-online.de>
Message-id: 20200516072014.7766-1-vr_qemu@t-online.de
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'ui')
-rw-r--r-- | ui/Makefile.objs | 3 | ||||
-rw-r--r-- | ui/win32-kbd-hook.c | 102 |
2 files changed, 105 insertions, 0 deletions
diff --git a/ui/Makefile.objs b/ui/Makefile.objs index e6da6ff..504b196 100644 --- a/ui/Makefile.objs +++ b/ui/Makefile.objs @@ -15,6 +15,9 @@ common-obj-$(CONFIG_SPICE) += spice-core.o spice-input.o spice-display.o common-obj-$(CONFIG_COCOA) += cocoa.o common-obj-$(CONFIG_VNC) += $(vnc-obj-y) common-obj-$(call lnot,$(CONFIG_VNC)) += vnc-stubs.o +ifneq (,$(findstring m,$(CONFIG_SDL)$(CONFIG_GTK))) +common-obj-$(CONFIG_WIN32) += win32-kbd-hook.o +endif # ui-sdl module common-obj-$(CONFIG_SDL) += sdl.mo diff --git a/ui/win32-kbd-hook.c b/ui/win32-kbd-hook.c new file mode 100644 index 0000000..1ac237d --- /dev/null +++ b/ui/win32-kbd-hook.c @@ -0,0 +1,102 @@ +/* + * This work is licensed under the terms of the GNU GPL, version 2 or + * (at your option) any later version. See the COPYING file in the + * top-level directory. + * + * The win32 keyboard hooking code was imported from project spice-gtk. + */ + +#include "qemu/osdep.h" +#include "sysemu/sysemu.h" +#include "ui/win32-kbd-hook.h" + +static Notifier win32_unhook_notifier; +static HHOOK win32_keyboard_hook; +static HWND win32_window; +static DWORD win32_grab; + +static LRESULT CALLBACK keyboard_hook_cb(int code, WPARAM wparam, LPARAM lparam) +{ + if (win32_window && code == HC_ACTION && win32_window == GetFocus()) { + KBDLLHOOKSTRUCT *hooked = (KBDLLHOOKSTRUCT *)lparam; + + if (wparam != WM_KEYUP) { + DWORD dwmsg = (hooked->flags << 24) | + ((hooked->scanCode & 0xff) << 16) | 1; + + switch (hooked->vkCode) { + case VK_CAPITAL: + /* fall through */ + case VK_SCROLL: + /* fall through */ + case VK_NUMLOCK: + /* fall through */ + case VK_LSHIFT: + /* fall through */ + case VK_RSHIFT: + /* fall through */ + case VK_RCONTROL: + /* fall through */ + case VK_LMENU: + /* fall through */ + case VK_RMENU: + break; + + case VK_LCONTROL: + /* + * When pressing AltGr, an extra VK_LCONTROL with a special + * scancode with bit 9 set is sent. Let's ignore the extra + * VK_LCONTROL, as that will make AltGr misbehave. + */ + if (hooked->scanCode & 0x200) { + return 1; + } + break; + + default: + if (win32_grab) { + SendMessage(win32_window, wparam, hooked->vkCode, dwmsg); + return 1; + } + break; + } + + } else { + switch (hooked->vkCode) { + case VK_LCONTROL: + if (hooked->scanCode & 0x200) { + return 1; + } + break; + } + } + } + + return CallNextHookEx(NULL, code, wparam, lparam); +} + +static void keyboard_hook_unhook(Notifier *n, void *data) +{ + UnhookWindowsHookEx(win32_keyboard_hook); + win32_keyboard_hook = NULL; +} + +void win32_kbd_set_window(void *hwnd) +{ + if (hwnd && !win32_keyboard_hook) { + /* note: the installing thread must have a message loop */ + win32_keyboard_hook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboard_hook_cb, + GetModuleHandle(NULL), 0); + if (win32_keyboard_hook) { + win32_unhook_notifier.notify = keyboard_hook_unhook; + qemu_add_exit_notifier(&win32_unhook_notifier); + } + } + + win32_window = hwnd; +} + +void win32_kbd_set_grab(bool grab) +{ + win32_grab = grab; +} |