Skip to content

Commit 3cb2a5c

Browse files
committedSep 3, 2020
(#20) Split keypress.c
1 parent 5fdcc66 commit 3cb2a5c

File tree

4 files changed

+298
-139
lines changed

4 files changed

+298
-139
lines changed
 

Diff for: ‎CMakeLists.txt

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ set(CMAKE_CXX_STANDARD 17)
44
project(libnut)
55

66
# Source
7-
set(SOURCE_FILES "src/main.cc" "src/deadbeef_rand.c" "src/keycode.c" "src/keypress.c" "src/MMBitmap.c" "src/screen.c" "src/screengrab.c")
7+
set(SOURCE_FILES "src/main.cc" "src/deadbeef_rand.c" "src/keycode.c" "src/MMBitmap.c" "src/screen.c" "src/screengrab.c")
88
if (UNIX AND NOT APPLE)
9-
set(SOURCE_FILES "${SOURCE_FILES}" "src/linux/mouse.c" "src/linux/xdisplay.c" "src/linux/highlightwindow.c" "src/linux/window_manager.cc")
9+
set(SOURCE_FILES "${SOURCE_FILES}" "src/linux/keypress.c" "src/linux/mouse.c" "src/linux/xdisplay.c" "src/linux/highlightwindow.c" "src/linux/window_manager.cc")
1010
elseif (UNIX AND APPLE)
11-
set(SOURCE_FILES "${SOURCE_FILES}" "src/macos/mouse.c" "src/macos/highlightwindow.m" "src/macos/window_manager.mm")
11+
set(SOURCE_FILES "${SOURCE_FILES}" "src/macos/keypress.c" "src/macos/mouse.c" "src/macos/highlightwindow.m" "src/macos/window_manager.mm")
1212
elseif (WIN32)
13-
set(SOURCE_FILES "${SOURCE_FILES}" "src/win32/mouse.c" "src/win32/highlightwindow.c" "src/win32/window_manager.cc")
13+
set(SOURCE_FILES "${SOURCE_FILES}" "src/win32/keypress.c" "src/win32/mouse.c" "src/win32/highlightwindow.c" "src/win32/window_manager.cc")
1414
endif()
1515
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})
1616

Diff for: ‎src/linux/keypress.c

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#include "../keypress.h"
2+
#include "../deadbeef_rand.h"
3+
#include "../microsleep.h"
4+
5+
#include <ctype.h> /* For isupper() */
6+
7+
#include <X11/extensions/XTest.h>
8+
#include "xdisplay.h"
9+
10+
#define X_KEY_EVENT(display, key, is_press) \
11+
(XTestFakeKeyEvent(display, \
12+
XKeysymToKeycode(display, key), \
13+
is_press, CurrentTime), \
14+
XSync(display, false))
15+
#define X_KEY_EVENT_WAIT(display, key, is_press) \
16+
(X_KEY_EVENT(display, key, is_press), \
17+
microsleep(DEADBEEF_UNIFORM(0.0, 62.5)))
18+
19+
void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags)
20+
{
21+
Display *display = XGetMainDisplay();
22+
const Bool is_press = down ? True : False; /* Just to be safe. */
23+
24+
/* Parse modifier keys. */
25+
if (flags & MOD_META) X_KEY_EVENT_WAIT(display, K_META, is_press);
26+
if (flags & MOD_ALT) X_KEY_EVENT_WAIT(display, K_ALT, is_press);
27+
if (flags & MOD_CONTROL) X_KEY_EVENT_WAIT(display, K_CONTROL, is_press);
28+
if (flags & MOD_SHIFT) X_KEY_EVENT_WAIT(display, K_SHIFT, is_press);
29+
30+
X_KEY_EVENT(display, code, is_press);
31+
}
32+
33+
void tapKeyCode(MMKeyCode code, MMKeyFlags flags)
34+
{
35+
toggleKeyCode(code, true, flags);
36+
toggleKeyCode(code, false, flags);
37+
}
38+
39+
void toggleKey(char c, const bool down, MMKeyFlags flags)
40+
{
41+
MMKeyCode keyCode = keyCodeForChar(c);
42+
43+
//Prevent unused variable warning for Mac and Linux.
44+
45+
if (isupper(c) && !(flags & MOD_SHIFT)) {
46+
flags |= MOD_SHIFT; /* Not sure if this is safe for all layouts. */
47+
}
48+
49+
toggleKeyCode(keyCode, down, flags);
50+
}
51+
52+
void tapKey(char c, MMKeyFlags flags)
53+
{
54+
toggleKey(c, true, flags);
55+
toggleKey(c, false, flags);
56+
}
57+
58+
#define toggleUniKey(c, down) toggleKey(c, down, MOD_NONE)
59+
60+
static void tapUniKey(char c)
61+
{
62+
toggleUniKey(c, true);
63+
toggleUniKey(c, false);
64+
}
65+
66+
void typeString(const char *str)
67+
{
68+
unsigned short c;
69+
unsigned short c1;
70+
unsigned short c2;
71+
unsigned short c3;
72+
unsigned long n;
73+
74+
while (*str != '\0') {
75+
c = *str++;
76+
77+
// warning, the following utf8 decoder
78+
// doesn't perform validation
79+
if (c <= 0x7F) {
80+
// 0xxxxxxx one byte
81+
n = c;
82+
} else if ((c & 0xE0) == 0xC0) {
83+
// 110xxxxx two bytes
84+
c1 = (*str++) & 0x3F;
85+
n = ((c & 0x1F) << 6) | c1;
86+
} else if ((c & 0xF0) == 0xE0) {
87+
// 1110xxxx three bytes
88+
c1 = (*str++) & 0x3F;
89+
c2 = (*str++) & 0x3F;
90+
n = ((c & 0x0F) << 12) | (c1 << 6) | c2;
91+
} else if ((c & 0xF8) == 0xF0) {
92+
// 11110xxx four bytes
93+
c1 = (*str++) & 0x3F;
94+
c2 = (*str++) & 0x3F;
95+
c3 = (*str++) & 0x3F;
96+
n = ((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
97+
}
98+
99+
toggleUniKey(n, true);
100+
toggleUniKey(n, false);
101+
}
102+
}
103+
104+
void typeStringDelayed(const char *str, const unsigned cpm)
105+
{
106+
/* Characters per second */
107+
const double cps = (double)cpm / 60.0;
108+
109+
/* Average milli-seconds per character */
110+
const double mspc = (cps == 0.0) ? 0.0 : 1000.0 / cps;
111+
112+
while (*str != '\0') {
113+
tapUniKey(*str++);
114+
microsleep(mspc + (DEADBEEF_UNIFORM(0.0, 62.5)));
115+
}
116+
}

Diff for: ‎src/keypress.c renamed to ‎src/macos/keypress.c

+7-135
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,13 @@
1-
#include "keypress.h"
2-
#include "deadbeef_rand.h"
3-
#include "microsleep.h"
1+
#include "../keypress.h"
2+
#include "../deadbeef_rand.h"
3+
#include "../microsleep.h"
44

55
#include <ctype.h> /* For isupper() */
66

7-
#if defined(IS_MACOSX)
8-
#include <ApplicationServices/ApplicationServices.h>
9-
#import <IOKit/hidsystem/IOHIDLib.h>
10-
#import <IOKit/hidsystem/ev_keymap.h>
11-
#elif defined(USE_X11)
12-
#include <X11/extensions/XTest.h>
13-
#include "xdisplay.h"
14-
#endif
7+
#include <ApplicationServices/ApplicationServices.h>
8+
#import <IOKit/hidsystem/IOHIDLib.h>
9+
#import <IOKit/hidsystem/ev_keymap.h>
1510

16-
/* Convenience wrappers around ugly APIs. */
17-
#if defined(IS_WINDOWS)
18-
#define WIN32_KEY_EVENT_WAIT(key, flags) \
19-
(win32KeyEvent(key, flags), Sleep(DEADBEEF_RANDRANGE(0, 63)))
20-
#elif defined(USE_X11)
21-
#define X_KEY_EVENT(display, key, is_press) \
22-
(XTestFakeKeyEvent(display, \
23-
XKeysymToKeycode(display, key), \
24-
is_press, CurrentTime), \
25-
XSync(display, false))
26-
#define X_KEY_EVENT_WAIT(display, key, is_press) \
27-
(X_KEY_EVENT(display, key, is_press), \
28-
microsleep(DEADBEEF_UNIFORM(0.0, 62.5)))
29-
#endif
30-
31-
#if defined(IS_MACOSX)
3211
static io_connect_t _getAuxiliaryKeyDriver(void)
3312
{
3413
static mach_port_t sEventDrvrRef = 0;
@@ -49,71 +28,9 @@ static io_connect_t _getAuxiliaryKeyDriver(void)
4928
}
5029
return sEventDrvrRef;
5130
}
52-
#endif
53-
54-
#if defined(IS_WINDOWS)
55-
void win32KeyEvent(int key, MMKeyFlags flags)
56-
{
57-
int scan = MapVirtualKey(key & 0xff, MAPVK_VK_TO_VSC);
58-
59-
/* Set the scan code for extended keys */
60-
switch (key)
61-
{
62-
case VK_RCONTROL:
63-
case VK_SNAPSHOT: /* Print Screen */
64-
case VK_RMENU: /* Right Alt / Alt Gr */
65-
case VK_PAUSE: /* Pause / Break */
66-
case VK_HOME:
67-
case VK_UP:
68-
case VK_PRIOR: /* Page up */
69-
case VK_LEFT:
70-
case VK_RIGHT:
71-
case VK_END:
72-
case VK_DOWN:
73-
case VK_NEXT: /* 'Page Down' */
74-
case VK_INSERT:
75-
case VK_DELETE:
76-
case VK_LWIN:
77-
case VK_RWIN:
78-
case VK_APPS: /* Application */
79-
case VK_VOLUME_MUTE:
80-
case VK_VOLUME_DOWN:
81-
case VK_VOLUME_UP:
82-
case VK_MEDIA_NEXT_TRACK:
83-
case VK_MEDIA_PREV_TRACK:
84-
case VK_MEDIA_STOP:
85-
case VK_MEDIA_PLAY_PAUSE:
86-
case VK_BROWSER_BACK:
87-
case VK_BROWSER_FORWARD:
88-
case VK_BROWSER_REFRESH:
89-
case VK_BROWSER_STOP:
90-
case VK_BROWSER_SEARCH:
91-
case VK_BROWSER_FAVORITES:
92-
case VK_BROWSER_HOME:
93-
case VK_LAUNCH_MAIL:
94-
{
95-
flags |= KEYEVENTF_EXTENDEDKEY;
96-
break;
97-
}
98-
}
99-
100-
/* Set the scan code for keyup */
101-
if ( flags & KEYEVENTF_KEYUP ) {
102-
scan |= 0x80;
103-
}
104-
105-
INPUT keyboardInput;
106-
keyboardInput.type = INPUT_KEYBOARD;
107-
keyboardInput.ki.wScan = scan;
108-
keyboardInput.ki.dwFlags = KEYEVENTF_SCANCODE | flags;
109-
keyboardInput.ki.time = 0;
110-
SendInput(1, &keyboardInput, sizeof(keyboardInput));
111-
}
112-
#endif
11331

11432
void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags)
11533
{
116-
#if defined(IS_MACOSX)
11734
/* The media keys all have 1000 added to them to help us detect them. */
11835
if (code >= 1000) {
11936
code = code - 1000; /* Get the real keycode. */
@@ -127,37 +44,14 @@ void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags)
12744
kr = IOHIDPostEvent( _getAuxiliaryKeyDriver(), NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE );
12845
assert( KERN_SUCCESS == kr );
12946
} else {
130-
CGEventRef keyEvent = CGEventCreateKeyboardEvent(NULL,
131-
(CGKeyCode)code, down);
47+
CGEventRef keyEvent = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)code, down);
13248
assert(keyEvent != NULL);
13349

13450
CGEventSetType(keyEvent, down ? kCGEventKeyDown : kCGEventKeyUp);
13551
CGEventSetFlags(keyEvent, flags);
13652
CGEventPost(kCGSessionEventTap, keyEvent);
13753
CFRelease(keyEvent);
13854
}
139-
#elif defined(IS_WINDOWS)
140-
const DWORD dwFlags = down ? 0 : KEYEVENTF_KEYUP;
141-
142-
/* Parse modifier keys. */
143-
if (flags & MOD_META) WIN32_KEY_EVENT_WAIT(K_META, dwFlags);
144-
if (flags & MOD_ALT) WIN32_KEY_EVENT_WAIT(K_ALT, dwFlags);
145-
if (flags & MOD_CONTROL) WIN32_KEY_EVENT_WAIT(K_CONTROL, dwFlags);
146-
if (flags & MOD_SHIFT) WIN32_KEY_EVENT_WAIT(K_SHIFT, dwFlags);
147-
148-
win32KeyEvent(code, dwFlags);
149-
#elif defined(USE_X11)
150-
Display *display = XGetMainDisplay();
151-
const Bool is_press = down ? True : False; /* Just to be safe. */
152-
153-
/* Parse modifier keys. */
154-
if (flags & MOD_META) X_KEY_EVENT_WAIT(display, K_META, is_press);
155-
if (flags & MOD_ALT) X_KEY_EVENT_WAIT(display, K_ALT, is_press);
156-
if (flags & MOD_CONTROL) X_KEY_EVENT_WAIT(display, K_CONTROL, is_press);
157-
if (flags & MOD_SHIFT) X_KEY_EVENT_WAIT(display, K_SHIFT, is_press);
158-
159-
X_KEY_EVENT(display, code, is_press);
160-
#endif
16155
}
16256

16357
void tapKeyCode(MMKeyCode code, MMKeyFlags flags)
@@ -170,22 +64,10 @@ void toggleKey(char c, const bool down, MMKeyFlags flags)
17064
{
17165
MMKeyCode keyCode = keyCodeForChar(c);
17266

173-
//Prevent unused variable warning for Mac and Linux.
174-
#if defined(IS_WINDOWS)
175-
int modifiers;
176-
#endif
177-
17867
if (isupper(c) && !(flags & MOD_SHIFT)) {
17968
flags |= MOD_SHIFT; /* Not sure if this is safe for all layouts. */
18069
}
18170

182-
#if defined(IS_WINDOWS)
183-
modifiers = keyCode >> 8; // Pull out modifers.
184-
if ((modifiers & 1) != 0) flags |= MOD_SHIFT; // Uptdate flags from keycode modifiers.
185-
if ((modifiers & 2) != 0) flags |= MOD_CONTROL;
186-
if ((modifiers & 4) != 0) flags |= MOD_ALT;
187-
keyCode = keyCode & 0xff; // Mask out modifiers.
188-
#endif
18971
toggleKeyCode(keyCode, down, flags);
19072
}
19173

@@ -195,7 +77,6 @@ void tapKey(char c, MMKeyFlags flags)
19577
toggleKey(c, false, flags);
19678
}
19779

198-
#if defined(IS_MACOSX)
19980
void toggleUnicodeKey(unsigned long ch, const bool down)
20081
{
20182
/* This function relies on the convenient
@@ -229,9 +110,6 @@ void toggleUniKey(char c, const bool down)
229110
{
230111
toggleUnicodeKey(c, down);
231112
}
232-
#else
233-
#define toggleUniKey(c, down) toggleKey(c, down, MOD_NONE)
234-
#endif
235113

236114
static void tapUniKey(char c)
237115
{
@@ -272,14 +150,8 @@ void typeString(const char *str)
272150
n = ((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
273151
}
274152

275-
#if defined(IS_MACOSX)
276153
toggleUnicodeKey(n, true);
277154
toggleUnicodeKey(n, false);
278-
#else
279-
toggleUniKey(n, true);
280-
toggleUniKey(n, false);
281-
#endif
282-
283155
}
284156
}
285157

Diff for: ‎src/win32/keypress.c

+171
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
#include "../keypress.h"
2+
#include "../deadbeef_rand.h"
3+
#include "../microsleep.h"
4+
5+
#include <ctype.h> /* For isupper() */
6+
7+
/* Convenience wrappers around ugly APIs. */
8+
#define WIN32_KEY_EVENT_WAIT(key, flags) \
9+
(win32KeyEvent(key, flags), Sleep(DEADBEEF_RANDRANGE(0, 63)))
10+
11+
void win32KeyEvent(int key, MMKeyFlags flags)
12+
{
13+
int scan = MapVirtualKey(key & 0xff, MAPVK_VK_TO_VSC);
14+
15+
/* Set the scan code for extended keys */
16+
switch (key)
17+
{
18+
case VK_RCONTROL:
19+
case VK_SNAPSHOT: /* Print Screen */
20+
case VK_RMENU: /* Right Alt / Alt Gr */
21+
case VK_PAUSE: /* Pause / Break */
22+
case VK_HOME:
23+
case VK_UP:
24+
case VK_PRIOR: /* Page up */
25+
case VK_LEFT:
26+
case VK_RIGHT:
27+
case VK_END:
28+
case VK_DOWN:
29+
case VK_NEXT: /* 'Page Down' */
30+
case VK_INSERT:
31+
case VK_DELETE:
32+
case VK_LWIN:
33+
case VK_RWIN:
34+
case VK_APPS: /* Application */
35+
case VK_VOLUME_MUTE:
36+
case VK_VOLUME_DOWN:
37+
case VK_VOLUME_UP:
38+
case VK_MEDIA_NEXT_TRACK:
39+
case VK_MEDIA_PREV_TRACK:
40+
case VK_MEDIA_STOP:
41+
case VK_MEDIA_PLAY_PAUSE:
42+
case VK_BROWSER_BACK:
43+
case VK_BROWSER_FORWARD:
44+
case VK_BROWSER_REFRESH:
45+
case VK_BROWSER_STOP:
46+
case VK_BROWSER_SEARCH:
47+
case VK_BROWSER_FAVORITES:
48+
case VK_BROWSER_HOME:
49+
case VK_LAUNCH_MAIL:
50+
{
51+
flags |= KEYEVENTF_EXTENDEDKEY;
52+
break;
53+
}
54+
}
55+
56+
/* Set the scan code for keyup */
57+
if ( flags & KEYEVENTF_KEYUP ) {
58+
scan |= 0x80;
59+
}
60+
61+
INPUT keyboardInput;
62+
keyboardInput.type = INPUT_KEYBOARD;
63+
keyboardInput.ki.wScan = scan;
64+
keyboardInput.ki.dwFlags = KEYEVENTF_SCANCODE | flags;
65+
keyboardInput.ki.time = 0;
66+
SendInput(1, &keyboardInput, sizeof(keyboardInput));
67+
}
68+
69+
void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags)
70+
{
71+
const DWORD dwFlags = down ? 0 : KEYEVENTF_KEYUP;
72+
73+
/* Parse modifier keys. */
74+
if (flags & MOD_META) WIN32_KEY_EVENT_WAIT(K_META, dwFlags);
75+
if (flags & MOD_ALT) WIN32_KEY_EVENT_WAIT(K_ALT, dwFlags);
76+
if (flags & MOD_CONTROL) WIN32_KEY_EVENT_WAIT(K_CONTROL, dwFlags);
77+
if (flags & MOD_SHIFT) WIN32_KEY_EVENT_WAIT(K_SHIFT, dwFlags);
78+
79+
win32KeyEvent(code, dwFlags);
80+
}
81+
82+
void tapKeyCode(MMKeyCode code, MMKeyFlags flags)
83+
{
84+
toggleKeyCode(code, true, flags);
85+
toggleKeyCode(code, false, flags);
86+
}
87+
88+
void toggleKey(char c, const bool down, MMKeyFlags flags)
89+
{
90+
MMKeyCode keyCode = keyCodeForChar(c);
91+
92+
//Prevent unused variable warning for Mac and Linux.
93+
int modifiers;
94+
95+
if (isupper(c) && !(flags & MOD_SHIFT)) {
96+
flags |= MOD_SHIFT; /* Not sure if this is safe for all layouts. */
97+
}
98+
99+
modifiers = keyCode >> 8; // Pull out modifers.
100+
if ((modifiers & 1) != 0) flags |= MOD_SHIFT; // Uptdate flags from keycode modifiers.
101+
if ((modifiers & 2) != 0) flags |= MOD_CONTROL;
102+
if ((modifiers & 4) != 0) flags |= MOD_ALT;
103+
keyCode = keyCode & 0xff; // Mask out modifiers.
104+
toggleKeyCode(keyCode, down, flags);
105+
}
106+
107+
void tapKey(char c, MMKeyFlags flags)
108+
{
109+
toggleKey(c, true, flags);
110+
toggleKey(c, false, flags);
111+
}
112+
113+
#define toggleUniKey(c, down) toggleKey(c, down, MOD_NONE)
114+
115+
static void tapUniKey(char c)
116+
{
117+
toggleUniKey(c, true);
118+
toggleUniKey(c, false);
119+
}
120+
121+
void typeString(const char *str)
122+
{
123+
unsigned short c;
124+
unsigned short c1;
125+
unsigned short c2;
126+
unsigned short c3;
127+
unsigned long n;
128+
129+
while (*str != '\0') {
130+
c = *str++;
131+
132+
// warning, the following utf8 decoder
133+
// doesn't perform validation
134+
if (c <= 0x7F) {
135+
// 0xxxxxxx one byte
136+
n = c;
137+
} else if ((c & 0xE0) == 0xC0) {
138+
// 110xxxxx two bytes
139+
c1 = (*str++) & 0x3F;
140+
n = ((c & 0x1F) << 6) | c1;
141+
} else if ((c & 0xF0) == 0xE0) {
142+
// 1110xxxx three bytes
143+
c1 = (*str++) & 0x3F;
144+
c2 = (*str++) & 0x3F;
145+
n = ((c & 0x0F) << 12) | (c1 << 6) | c2;
146+
} else if ((c & 0xF8) == 0xF0) {
147+
// 11110xxx four bytes
148+
c1 = (*str++) & 0x3F;
149+
c2 = (*str++) & 0x3F;
150+
c3 = (*str++) & 0x3F;
151+
n = ((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3;
152+
}
153+
154+
toggleUniKey(n, true);
155+
toggleUniKey(n, false);
156+
}
157+
}
158+
159+
void typeStringDelayed(const char *str, const unsigned cpm)
160+
{
161+
/* Characters per second */
162+
const double cps = (double)cpm / 60.0;
163+
164+
/* Average milli-seconds per character */
165+
const double mspc = (cps == 0.0) ? 0.0 : 1000.0 / cps;
166+
167+
while (*str != '\0') {
168+
tapUniKey(*str++);
169+
microsleep(mspc + (DEADBEEF_UNIFORM(0.0, 62.5)));
170+
}
171+
}

0 commit comments

Comments
 (0)
Please sign in to comment.