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; | ||
|  | } |