qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

win32-kbd-hook.c (2986B)


      1 /*
      2  * This work is licensed under the terms of the GNU GPL, version 2 or
      3  * (at your option) any later version.  See the COPYING file in the
      4  * top-level directory.
      5  *
      6  * The win32 keyboard hooking code was imported from project spice-gtk.
      7  */
      8 
      9 #include "qemu/osdep.h"
     10 #include "sysemu/sysemu.h"
     11 #include "ui/win32-kbd-hook.h"
     12 
     13 static Notifier win32_unhook_notifier;
     14 static HHOOK win32_keyboard_hook;
     15 static HWND win32_window;
     16 static DWORD win32_grab;
     17 
     18 static LRESULT CALLBACK keyboard_hook_cb(int code, WPARAM wparam, LPARAM lparam)
     19 {
     20     if  (win32_window && code == HC_ACTION && win32_window == GetFocus()) {
     21         KBDLLHOOKSTRUCT *hooked = (KBDLLHOOKSTRUCT *)lparam;
     22 
     23         if (wparam != WM_KEYUP) {
     24             DWORD dwmsg = (hooked->flags << 24) |
     25                           ((hooked->scanCode & 0xff) << 16) | 1;
     26 
     27             switch (hooked->vkCode) {
     28             case VK_CAPITAL:
     29                 /* fall through */
     30             case VK_SCROLL:
     31                 /* fall through */
     32             case VK_NUMLOCK:
     33                 /* fall through */
     34             case VK_LSHIFT:
     35                 /* fall through */
     36             case VK_RSHIFT:
     37                 /* fall through */
     38             case VK_RCONTROL:
     39                 /* fall through */
     40             case VK_LMENU:
     41                 /* fall through */
     42             case VK_RMENU:
     43                 break;
     44 
     45             case VK_LCONTROL:
     46                 /*
     47                  * When pressing AltGr, an extra VK_LCONTROL with a special
     48                  * scancode with bit 9 set is sent. Let's ignore the extra
     49                  * VK_LCONTROL, as that will make AltGr misbehave.
     50                  */
     51                 if (hooked->scanCode & 0x200) {
     52                     return 1;
     53                 }
     54                 break;
     55 
     56             default:
     57                 if (win32_grab) {
     58                     SendMessage(win32_window, wparam, hooked->vkCode, dwmsg);
     59                     return 1;
     60                 }
     61                 break;
     62             }
     63 
     64         } else {
     65             switch (hooked->vkCode) {
     66             case VK_LCONTROL:
     67                 if (hooked->scanCode & 0x200) {
     68                     return 1;
     69                 }
     70                 break;
     71             }
     72         }
     73     }
     74 
     75     return CallNextHookEx(NULL, code, wparam, lparam);
     76 }
     77 
     78 static void keyboard_hook_unhook(Notifier *n, void *data)
     79 {
     80     UnhookWindowsHookEx(win32_keyboard_hook);
     81     win32_keyboard_hook = NULL;
     82 }
     83 
     84 void win32_kbd_set_window(void *hwnd)
     85 {
     86     if (hwnd && !win32_keyboard_hook) {
     87         /* note: the installing thread must have a message loop */
     88         win32_keyboard_hook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboard_hook_cb,
     89                                                GetModuleHandle(NULL), 0);
     90         if (win32_keyboard_hook) {
     91             win32_unhook_notifier.notify = keyboard_hook_unhook;
     92             qemu_add_exit_notifier(&win32_unhook_notifier);
     93         }
     94     }
     95 
     96     win32_window = hwnd;
     97 }
     98 
     99 void win32_kbd_set_grab(bool grab)
    100 {
    101     win32_grab = grab;
    102 }