blob: d75cc578984b5811f6b5530e0caab1f29ef6f87c [file] [log] [blame]
Pierre Ossman407a5c32011-05-26 14:48:29 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
2 * Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
3 *
4 * This is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This software is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this software; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 * USA.
18 */
19
20#include <windows.h>
21
22static HANDLE thread;
23static DWORD thread_id;
24
25static HHOOK hook = 0;
26static HWND target_wnd = 0;
27
28static int is_system_hotkey(int vkCode) {
29 switch (vkCode) {
30 case VK_LWIN:
31 case VK_RWIN:
32 case VK_SNAPSHOT:
33 return 1;
34 case VK_TAB:
35 if (GetAsyncKeyState(VK_MENU) & 0x8000)
36 return 1;
37 case VK_ESCAPE:
38 if (GetAsyncKeyState(VK_MENU) & 0x8000)
39 return 1;
40 if (GetAsyncKeyState(VK_CONTROL) & 0x8000)
41 return 1;
42 }
43 return 0;
44}
45
46static LRESULT CALLBACK keyboard_hook(int nCode, WPARAM wParam, LPARAM lParam)
47{
48 if (nCode >= 0) {
49 KBDLLHOOKSTRUCT* msgInfo = (KBDLLHOOKSTRUCT*)lParam;
50
51 // Grabbing everything seems to mess up some keyboard state that
52 // FLTK relies on, so just grab the keys that we normally cannot.
53 if (is_system_hotkey(msgInfo->vkCode)) {
54 PostMessage(target_wnd, wParam, msgInfo->vkCode,
55 (msgInfo->scanCode & 0xff) << 16 |
56 (msgInfo->flags & 0xff) << 24);
57 return 1;
58 }
59 }
60
61 return CallNextHookEx(hook, nCode, wParam, lParam);
62}
63
64static DWORD WINAPI keyboard_thread(LPVOID data)
65{
66 MSG msg;
67
68 target_wnd = (HWND)data;
69
70 // Make sure a message queue is created
71 PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE | PM_NOYIELD);
72
73 hook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboard_hook, GetModuleHandle(0), 0);
74 // If something goes wrong then there is not much we can do.
75 // Just sit around and wait for WM_QUIT...
76
77 while (GetMessage(&msg, NULL, 0, 0));
78
79 if (hook)
80 UnhookWindowsHookEx(hook);
81
82 target_wnd = 0;
83
84 return 0;
85}
86
87int win32_enable_lowlevel_keyboard(HWND hwnd)
88{
89 // Only one target at a time for now
90 if (thread != NULL) {
91 if (hwnd == target_wnd)
92 return 0;
93
94 return 1;
95 }
96
97 // We create a separate thread as it is crucial that hooks are processed
98 // in a timely manner.
99 thread = CreateThread(NULL, 0, keyboard_thread, hwnd, 0, &thread_id);
100 if (thread == NULL)
101 return 1;
102
103 return 0;
104}
105
106void win32_disable_lowlevel_keyboard(HWND hwnd)
107{
108 if (hwnd != target_wnd)
109 return;
110
111 PostThreadMessage(thread_id, WM_QUIT, 0, 0);
112
113 CloseHandle(thread);
114 thread = NULL;
115}