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>
		
			
				
	
	
		
			103 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			103 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * 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;
 | |
| }
 |