forked from kmonad/kmonad
-
Notifications
You must be signed in to change notification settings - Fork 0
/
keyio_win.c
266 lines (213 loc) · 6.29 KB
/
keyio_win.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
// Necessary to get mingw to compile for some reason
/* #define WINVER 0x0601 */
/* #define _WIN32_WINNT 0x0601 */
#include <windows.h>
#include <stdbool.h>
#include <stdio.h>
// Type of the key event: 0 Press, 1 Release, 2 Repeat
typedef unsigned char ACTION;
ACTION KEY_PRESS = 0;
ACTION KEY_RELEASE = 1;
// All the information KMonad needs about a key-event
struct KeyEvent {
ACTION type;
DWORD keycode;
} KeyEvent;
// Variables we need to access globally
HANDLE readPipe = NULL;
HANDLE writePipe = NULL;
HHOOK hookHandle;
// Print last error and exit program
void last_error()
{ LPVOID lpMsgBuf;
DWORD dw = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL);
//printf("C: Error: %s", lpMsgBuf);
exit(dw);
}
// Callback we insert into windows that writes events to pipe
LRESULT CALLBACK keyHandler(int nCode, WPARAM wParam, LPARAM lParam)
{
// Cast the lParam to a keyboard-event struct
KBDLLHOOKSTRUCT* e = (KBDLLHOOKSTRUCT*)(lParam);
// Skip processing if nCode is 0 or this is an injected event
if (nCode < 0 || e->flags & LLKHF_INJECTED) {
return CallNextHookEx(hookHandle, nCode, wParam, lParam);
};
// Create the KEY_EVENT matching the current event
ACTION type;
switch (wParam) {
case WM_KEYDOWN:
type = KEY_PRESS;
break;
case WM_SYSKEYDOWN:
type = KEY_PRESS;
break;
case WM_KEYUP:
type = KEY_RELEASE;
break;
case WM_SYSKEYUP:
type = KEY_RELEASE;
break;
};
// Construct the KeyEvent to write to the pipe
struct KeyEvent ev;
ev.type = type;
ev.keycode = e->vkCode;
// Write the event to the pipe
DWORD dwWritten;
WriteFile(writePipe, &ev, sizeof(ev), &dwWritten, NULL);
}
// Read an event from the pipe and write it to the provided pointer
void wait_key(struct KeyEvent* e)
{
DWORD dwRead;
ReadFile(readPipe, e, sizeof(e), &dwRead, NULL);
//printf("receiving: %d\n", e->keycode);
return;
}
// Insert the keyboard hook and start the monitoring process
int grab_kb()
{
// Insert the hook, error on failure
hookHandle = SetWindowsHookEx(WH_KEYBOARD_LL, keyHandler, NULL, 0);
if (hookHandle == NULL) last_error();
// Create the pipe, error on failure
if ( !CreatePipe(&readPipe, &writePipe, NULL, 0) ) last_error();
// This *never* triggers, but if not included the program doesn't run..?
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{ TranslateMessage(&msg);
DispatchMessage(&msg); }
}
// Uninstall the keyboard hook and kill the process
int release_kb()
{
UnhookWindowsHookEx(hookHandle);
PostQuitMessage(0);
return(0);
}
// Send key to the OS
void sendKey(struct KeyEvent* e)
{
INPUT ip;
// Standard stuff we don't use
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0;
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
ip.ki.wVk = e->keycode;
switch (e->type) {
case 0:
ip.ki.dwFlags = 0;
break;
case 1:
ip.ki.dwFlags = KEYEVENTF_KEYUP;
break;
}
//printf("emitting kc: %d\n", ip.ki.wVk);
// Emit the event to the OS
SendInput(1, &ip, sizeof(INPUT));
}
// OLD STUFF FOR FUTURE REFERENCE
// Tell windows to start sending all keyboard events to hTarget
/* bool HID_RegisterDevice(HWND hTarget, USHORT usage)
{
RAWINPUTDEVICE hid[1];
hid[0].usUsagePage = 0x01;
hid[0].usUsage = usage;
hid[0].dwFlags = RIDEV_INPUTSINK; // RIDEV_DEVNOTIFY RIDEV_NOLEGACY
hid[0].hwndTarget = hTarget;
return RegisterRawInputDevices(&hid, 1, sizeof(RAWINPUTDEVICE));
}
*/
/* void grab_keyboard(HWND hTarget)
{
RAWINPUTDEVICE ri[1];
ri[0].usUsagePage = 0x01;
ri[0].usUsage = 0x06;
ri[0].dwFlags = RIDEV_NOLEGACY | RIDEV_INPUTSINK;
ri[0].hwndTarget = hTarget;
if (RegisterRawInputDevices(ri, 1, sizeof(ri[0])) == FALSE) {
last_error();
}
}
*/
/*
// Tell windows to stop sending all keyboard events to hTarget
void HID_UnregisterDevice(USHORT usage)
{
RAWINPUTDEVICE hid;
hid.usUsagePage = 1;
hid.usUsage = usage;
hid.dwFlags = RIDEV_REMOVE;
hid.hwndTarget = NULL;
RegisterRawInputDevices(&hid, 1, sizeof(RAWINPUTDEVICE));
} */
/* Make windows class and window
//const wchar_t CLASS_NAME[] = L"Sample Window Class";
static const char* CLASS_NAME = "MESSAGE_ONLY";
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0x0;
wc.lpszClassName = CLASS_NAME;
wc.lpfnWndProc = callback;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszMenuName = 0;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hbrBackground = NULL;
fprintf(stdout, "trying to make window class\n");
if ( !RegisterClassEx(&wc) ) { last_error(); }
fprintf(stdout, "succeeded");
fprintf(stdout, "hello\n");
HWND hwnd = CreateWindowEx(
0,
CLASS_NAME, // Window class
"kmonad", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
0,0,0,0,
HWND_MESSAGE, // Parent: message only window
NULL, // Menu
hInstance, // Instance
NULL // Additional data
);
ShowWindow(hwnd, cmd_show);
// Windows event callback
LRESULT CALLBACK callback(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg) {
case WM_DESTROY: {
PostQuitMessage(0);
return 0;
}
case WM_CLOSE: {
DestroyWindow(hwnd);
return 0;
}
case WM_INPUT: {
fprintf(stdout, "hello");
UINT dwSize;
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
//LPBYTE lpb = new BYTE[dwSize];
//inf (lpb == NULL) {
// return 0; }
return 0;
}
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrev, LPSTR cmd_line, int cmd_show)
{
*/