|
8 | 8 | #import <IOKit/hidsystem/IOHIDLib.h>
|
9 | 9 | #import <IOKit/hidsystem/ev_keymap.h>
|
10 | 10 |
|
11 |
| -static io_connect_t _getAuxiliaryKeyDriver(void) |
12 |
| -{ |
13 |
| - static mach_port_t sEventDrvrRef = 0; |
14 |
| - mach_port_t masterPort, service, iter; |
15 |
| - kern_return_t kr; |
16 |
| - |
17 |
| - if (!sEventDrvrRef) |
18 |
| - { |
19 |
| - kr = IOMasterPort(bootstrap_port, &masterPort); |
20 |
| - assert(KERN_SUCCESS == kr); |
21 |
| - kr = IOServiceGetMatchingServices(masterPort, IOServiceMatching(kIOHIDSystemClass), &iter); |
22 |
| - assert(KERN_SUCCESS == kr); |
23 |
| - service = IOIteratorNext(iter); |
24 |
| - assert(service); |
25 |
| - kr = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, &sEventDrvrRef); |
26 |
| - assert(KERN_SUCCESS == kr); |
27 |
| - IOObjectRelease(service); |
28 |
| - IOObjectRelease(iter); |
29 |
| - } |
30 |
| - return sEventDrvrRef; |
| 11 | +MMKeyFlags flagBuffer; |
| 12 | + |
| 13 | +static io_connect_t _getAuxiliaryKeyDriver(void) { |
| 14 | + static mach_port_t sEventDrvrRef = 0; |
| 15 | + mach_port_t masterPort, service, iter; |
| 16 | + kern_return_t kr; |
| 17 | + |
| 18 | + if (!sEventDrvrRef) { |
| 19 | + kr = IOMasterPort(bootstrap_port, &masterPort); |
| 20 | + assert(KERN_SUCCESS == kr); |
| 21 | + kr = IOServiceGetMatchingServices( |
| 22 | + masterPort, IOServiceMatching(kIOHIDSystemClass), &iter); |
| 23 | + assert(KERN_SUCCESS == kr); |
| 24 | + service = IOIteratorNext(iter); |
| 25 | + assert(service); |
| 26 | + kr = IOServiceOpen(service, mach_task_self(), kIOHIDParamConnectType, |
| 27 | + &sEventDrvrRef); |
| 28 | + assert(KERN_SUCCESS == kr); |
| 29 | + IOObjectRelease(service); |
| 30 | + IOObjectRelease(iter); |
| 31 | + } |
| 32 | + return sEventDrvrRef; |
31 | 33 | }
|
32 | 34 |
|
33 |
| -void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags) |
34 |
| -{ |
35 |
| - /* The media keys all have 1000 added to them to help us detect them. */ |
36 |
| - if (code >= 1000) |
37 |
| - { |
38 |
| - code = code - 1000; /* Get the real keycode. */ |
39 |
| - NXEventData event; |
40 |
| - kern_return_t kr; |
41 |
| - IOGPoint loc = {0, 0}; |
42 |
| - UInt32 evtInfo = code << 16 | (down ? NX_KEYDOWN : NX_KEYUP) << 8; |
43 |
| - bzero(&event, sizeof(NXEventData)); |
44 |
| - event.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS; |
45 |
| - event.compound.misc.L[0] = evtInfo; |
46 |
| - kr = IOHIDPostEvent(_getAuxiliaryKeyDriver(), NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE); |
47 |
| - assert(KERN_SUCCESS == kr); |
48 |
| - } |
49 |
| - else |
50 |
| - { |
51 |
| - CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStatePrivate); |
52 |
| - CGEventRef keyEvent = CGEventCreateKeyboardEvent(src, (CGKeyCode)code, down); |
53 |
| - assert(keyEvent != NULL); |
54 |
| - |
55 |
| - CGEventSetFlags(keyEvent, flags); |
56 |
| - CGEventPost(kCGHIDEventTap, keyEvent); |
57 |
| - CFRelease(keyEvent); |
58 |
| - CFRelease(src); |
59 |
| - } |
| 35 | +void toggleKeyCode(MMKeyCode code, const bool down, MMKeyFlags flags) { |
| 36 | + /* The media keys all have 1000 added to them to help us detect them. */ |
| 37 | + if (code >= 1000) { |
| 38 | + code = code - 1000; /* Get the real keycode. */ |
| 39 | + NXEventData event; |
| 40 | + kern_return_t kr; |
| 41 | + IOGPoint loc = {0, 0}; |
| 42 | + UInt32 evtInfo = code << 16 | (down ? NX_KEYDOWN : NX_KEYUP) << 8; |
| 43 | + bzero(&event, sizeof(NXEventData)); |
| 44 | + event.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS; |
| 45 | + event.compound.misc.L[0] = evtInfo; |
| 46 | + kr = IOHIDPostEvent(_getAuxiliaryKeyDriver(), NX_SYSDEFINED, loc, &event, |
| 47 | + kNXEventDataVersion, 0, FALSE); |
| 48 | + assert(KERN_SUCCESS == kr); |
| 49 | + } else { |
| 50 | + CGEventSourceRef src = |
| 51 | + CGEventSourceCreate(kCGEventSourceStateHIDSystemState); |
| 52 | + CGEventRef keyEvent = |
| 53 | + CGEventCreateKeyboardEvent(src, (CGKeyCode)code, down); |
| 54 | + assert(keyEvent != NULL); |
| 55 | + |
| 56 | + // Check if keycode is one of the available modifier keys and set keyflags |
| 57 | + // accordingly |
| 58 | + if (code == K_META) { |
| 59 | + flags |= MOD_META; |
| 60 | + } |
| 61 | + if (code == K_ALT) { |
| 62 | + flags |= MOD_ALT; |
| 63 | + } |
| 64 | + if (code == K_CONTROL) { |
| 65 | + flags |= MOD_CONTROL; |
| 66 | + } |
| 67 | + if (code == K_SHIFT || code == K_RIGHTSHIFT) { |
| 68 | + flags |= MOD_SHIFT; |
| 69 | + } |
| 70 | + |
| 71 | + MMKeyFlags activeKeyFlags; |
| 72 | + if (down) { |
| 73 | + activeKeyFlags = flags | flagBuffer; |
| 74 | + flagBuffer |= activeKeyFlags; |
| 75 | + } else { |
| 76 | + activeKeyFlags = flags ^ flagBuffer; |
| 77 | + flagBuffer ^= flags; |
| 78 | + } |
| 79 | + |
| 80 | + CGEventSetFlags(keyEvent, activeKeyFlags); |
| 81 | + CGEventPost(kCGHIDEventTap, keyEvent); |
| 82 | + CFRelease(keyEvent); |
| 83 | + CFRelease(src); |
| 84 | + } |
60 | 85 | }
|
61 | 86 |
|
62 |
| -void tapKeyCode(MMKeyCode code, MMKeyFlags flags) |
63 |
| -{ |
64 |
| - toggleKeyCode(code, true, flags); |
65 |
| - toggleKeyCode(code, false, flags); |
| 87 | +void tapKeyCode(MMKeyCode code, MMKeyFlags flags) { |
| 88 | + toggleKeyCode(code, true, flags); |
| 89 | + toggleKeyCode(code, false, flags); |
66 | 90 | }
|
67 | 91 |
|
68 |
| -void toggleKey(char c, const bool down, MMKeyFlags flags) |
69 |
| -{ |
70 |
| - MMKeyCode keyCode = keyCodeForChar(c); |
| 92 | +void toggleKey(char c, const bool down, MMKeyFlags flags) { |
| 93 | + MMKeyCode keyCode = keyCodeForChar(c); |
71 | 94 |
|
72 |
| - if (isupper(c) && !(flags & MOD_SHIFT)) |
73 |
| - { |
74 |
| - flags |= MOD_SHIFT; /* Not sure if this is safe for all layouts. */ |
75 |
| - } |
| 95 | + if (isupper(c) && !(flags & MOD_SHIFT)) { |
| 96 | + flags |= MOD_SHIFT; /* Not sure if this is safe for all layouts. */ |
| 97 | + } |
76 | 98 |
|
77 |
| - toggleKeyCode(keyCode, down, flags); |
| 99 | + toggleKeyCode(keyCode, down, flags); |
78 | 100 | }
|
79 | 101 |
|
80 |
| -void tapKey(char c, MMKeyFlags flags) |
81 |
| -{ |
82 |
| - toggleKey(c, true, flags); |
83 |
| - toggleKey(c, false, flags); |
| 102 | +void tapKey(char c, MMKeyFlags flags) { |
| 103 | + toggleKey(c, true, flags); |
| 104 | + toggleKey(c, false, flags); |
84 | 105 | }
|
85 | 106 |
|
86 |
| -void toggleUnicodeKey(unsigned long ch, const bool down) |
87 |
| -{ |
88 |
| - /* This function relies on the convenient |
89 |
| - * CGEventKeyboardSetUnicodeString(), which allows us to not have to |
90 |
| - * convert characters to a keycode, but does not support adding modifier |
91 |
| - * flags. It is therefore only used in typeString() and typeStringDelayed() |
92 |
| - * -- if you need modifier keys, use the above functions instead. */ |
93 |
| - CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStatePrivate); |
94 |
| - CGEventRef keyEvent = CGEventCreateKeyboardEvent(src, 0, down); |
95 |
| - if (keyEvent == NULL) |
96 |
| - { |
97 |
| - fputs("Could not create keyboard event.\n", stderr); |
98 |
| - return; |
99 |
| - } |
100 |
| - |
101 |
| - if (ch > 0xFFFF) |
102 |
| - { |
103 |
| - // encode to utf-16 if necessary |
104 |
| - unsigned short surrogates[] = { |
105 |
| - 0xD800 + ((ch - 0x10000) >> 10), |
106 |
| - 0xDC00 + (ch & 0x3FF)}; |
107 |
| - |
108 |
| - CGEventKeyboardSetUnicodeString(keyEvent, 2, &surrogates); |
109 |
| - } |
110 |
| - else |
111 |
| - { |
112 |
| - CGEventKeyboardSetUnicodeString(keyEvent, 1, &ch); |
113 |
| - } |
114 |
| - |
115 |
| - CGEventPost(kCGHIDEventTap, keyEvent); |
116 |
| - CFRelease(keyEvent); |
117 |
| - CFRelease(src); |
| 107 | +void toggleUnicodeKey(unsigned long ch, const bool down) { |
| 108 | + /* This function relies on the convenient |
| 109 | + * CGEventKeyboardSetUnicodeString(), which allows us to not have to |
| 110 | + * convert characters to a keycode, but does not support adding modifier |
| 111 | + * flags. It is therefore only used in typeString() and typeStringDelayed() |
| 112 | + * -- if you need modifier keys, use the above functions instead. */ |
| 113 | + CGEventSourceRef src = CGEventSourceCreate(kCGEventSourceStateHIDSystemState); |
| 114 | + CGEventRef keyEvent = CGEventCreateKeyboardEvent(src, 0, down); |
| 115 | + if (keyEvent == NULL) { |
| 116 | + fputs("Could not create keyboard event.\n", stderr); |
| 117 | + return; |
| 118 | + } |
| 119 | + |
| 120 | + if (ch > 0xFFFF) { |
| 121 | + // encode to utf-16 if necessary |
| 122 | + unsigned short surrogates[] = {0xD800 + ((ch - 0x10000) >> 10), |
| 123 | + 0xDC00 + (ch & 0x3FF)}; |
| 124 | + |
| 125 | + CGEventKeyboardSetUnicodeString(keyEvent, 2, &surrogates); |
| 126 | + } else { |
| 127 | + CGEventKeyboardSetUnicodeString(keyEvent, 1, &ch); |
| 128 | + } |
| 129 | + |
| 130 | + CGEventPost(kCGHIDEventTap, keyEvent); |
| 131 | + CFRelease(keyEvent); |
| 132 | + CFRelease(src); |
118 | 133 | }
|
119 | 134 |
|
120 |
| -void toggleUniKey(char c, const bool down) |
121 |
| -{ |
122 |
| - toggleUnicodeKey(c, down); |
123 |
| -} |
| 135 | +void toggleUniKey(char c, const bool down) { toggleUnicodeKey(c, down); } |
124 | 136 |
|
125 |
| -static void tapUniKey(char c) |
126 |
| -{ |
127 |
| - toggleUniKey(c, true); |
128 |
| - toggleUniKey(c, false); |
| 137 | +static void tapUniKey(char c) { |
| 138 | + toggleUniKey(c, true); |
| 139 | + toggleUniKey(c, false); |
129 | 140 | }
|
130 | 141 |
|
131 |
| -void typeString(const char *str) |
132 |
| -{ |
133 |
| - unsigned short c; |
134 |
| - unsigned short c1; |
135 |
| - unsigned short c2; |
136 |
| - unsigned short c3; |
137 |
| - unsigned long n; |
138 |
| - |
139 |
| - while (*str != '\0') |
140 |
| - { |
141 |
| - c = *str++; |
142 |
| - |
143 |
| - // warning, the following utf8 decoder |
144 |
| - // doesn't perform validation |
145 |
| - if (c <= 0x7F) |
146 |
| - { |
147 |
| - // 0xxxxxxx one byte |
148 |
| - n = c; |
149 |
| - } |
150 |
| - else if ((c & 0xE0) == 0xC0) |
151 |
| - { |
152 |
| - // 110xxxxx two bytes |
153 |
| - c1 = (*str++) & 0x3F; |
154 |
| - n = ((c & 0x1F) << 6) | c1; |
155 |
| - } |
156 |
| - else if ((c & 0xF0) == 0xE0) |
157 |
| - { |
158 |
| - // 1110xxxx three bytes |
159 |
| - c1 = (*str++) & 0x3F; |
160 |
| - c2 = (*str++) & 0x3F; |
161 |
| - n = ((c & 0x0F) << 12) | (c1 << 6) | c2; |
162 |
| - } |
163 |
| - else if ((c & 0xF8) == 0xF0) |
164 |
| - { |
165 |
| - // 11110xxx four bytes |
166 |
| - c1 = (*str++) & 0x3F; |
167 |
| - c2 = (*str++) & 0x3F; |
168 |
| - c3 = (*str++) & 0x3F; |
169 |
| - n = ((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3; |
170 |
| - } |
171 |
| - |
172 |
| - toggleUnicodeKey(n, true); |
173 |
| - toggleUnicodeKey(n, false); |
174 |
| - } |
| 142 | +void typeString(const char *str) { |
| 143 | + unsigned short c; |
| 144 | + unsigned short c1; |
| 145 | + unsigned short c2; |
| 146 | + unsigned short c3; |
| 147 | + unsigned long n; |
| 148 | + |
| 149 | + while (*str != '\0') { |
| 150 | + c = *str++; |
| 151 | + |
| 152 | + // warning, the following utf8 decoder |
| 153 | + // doesn't perform validation |
| 154 | + if (c <= 0x7F) { |
| 155 | + // 0xxxxxxx one byte |
| 156 | + n = c; |
| 157 | + } else if ((c & 0xE0) == 0xC0) { |
| 158 | + // 110xxxxx two bytes |
| 159 | + c1 = (*str++) & 0x3F; |
| 160 | + n = ((c & 0x1F) << 6) | c1; |
| 161 | + } else if ((c & 0xF0) == 0xE0) { |
| 162 | + // 1110xxxx three bytes |
| 163 | + c1 = (*str++) & 0x3F; |
| 164 | + c2 = (*str++) & 0x3F; |
| 165 | + n = ((c & 0x0F) << 12) | (c1 << 6) | c2; |
| 166 | + } else if ((c & 0xF8) == 0xF0) { |
| 167 | + // 11110xxx four bytes |
| 168 | + c1 = (*str++) & 0x3F; |
| 169 | + c2 = (*str++) & 0x3F; |
| 170 | + c3 = (*str++) & 0x3F; |
| 171 | + n = ((c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3; |
| 172 | + } |
| 173 | + |
| 174 | + toggleUnicodeKey(n, true); |
| 175 | + toggleUnicodeKey(n, false); |
| 176 | + } |
175 | 177 | }
|
176 | 178 |
|
177 |
| -void typeStringDelayed(const char *str, const unsigned cpm) |
178 |
| -{ |
179 |
| - /* Characters per second */ |
180 |
| - const double cps = (double)cpm / 60.0; |
| 179 | +void typeStringDelayed(const char *str, const unsigned cpm) { |
| 180 | + /* Characters per second */ |
| 181 | + const double cps = (double)cpm / 60.0; |
181 | 182 |
|
182 |
| - /* Average milli-seconds per character */ |
183 |
| - const double mspc = (cps == 0.0) ? 0.0 : 1000.0 / cps; |
| 183 | + /* Average milli-seconds per character */ |
| 184 | + const double mspc = (cps == 0.0) ? 0.0 : 1000.0 / cps; |
184 | 185 |
|
185 |
| - while (*str != '\0') |
186 |
| - { |
187 |
| - tapUniKey(*str++); |
188 |
| - microsleep(mspc + (DEADBEEF_UNIFORM(0.0, 62.5))); |
189 |
| - } |
| 186 | + while (*str != '\0') { |
| 187 | + tapUniKey(*str++); |
| 188 | + microsleep(mspc + (DEADBEEF_UNIFORM(0.0, 62.5))); |
| 189 | + } |
190 | 190 | }
|
0 commit comments