]>
Commit | Line | Data |
---|---|---|
a02a5cfc KO |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: src/osx/uiaction_osx.cpp | |
3 | // Purpose: wxUIActionSimulator implementation | |
571d991b | 4 | // Author: Kevin Ollivier, Steven Lamerton, Vadim Zeitlin |
a02a5cfc KO |
5 | // Modified by: |
6 | // Created: 2010-03-06 | |
b5b208a1 | 7 | // RCS-ID: $Id$ |
a02a5cfc | 8 | // Copyright: (c) Kevin Ollivier |
571d991b VZ |
9 | // (c) 2010 Steven Lamerton |
10 | // (c) 2010 Vadim Zeitlin | |
a02a5cfc KO |
11 | // Licence: wxWindows licence |
12 | ///////////////////////////////////////////////////////////////////////////// | |
13 | ||
9b7e0226 VZ |
14 | #include "wx/defs.h" |
15 | ||
16 | #if wxUSE_UIACTIONSIMULATOR | |
17 | ||
18 | #include "wx/uiaction.h" | |
a02a5cfc | 19 | |
571d991b VZ |
20 | #include "wx/log.h" |
21 | ||
22 | #include "wx/osx/private.h" | |
23 | #include "wx/osx/core/cfref.h" | |
24 | ||
25 | namespace | |
26 | { | |
a02a5cfc | 27 | |
eeb7bdd0 SC |
28 | #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 |
29 | ||
30 | // adding forward compatible defines for keys that are different on different keyboard layouts | |
31 | // see Inside Mac Volume V | |
32 | ||
33 | enum { | |
34 | kVK_ANSI_A = 0x00, | |
35 | kVK_ANSI_S = 0x01, | |
36 | kVK_ANSI_D = 0x02, | |
37 | kVK_ANSI_F = 0x03, | |
38 | kVK_ANSI_H = 0x04, | |
39 | kVK_ANSI_G = 0x05, | |
40 | kVK_ANSI_Z = 0x06, | |
41 | kVK_ANSI_X = 0x07, | |
42 | kVK_ANSI_C = 0x08, | |
43 | kVK_ANSI_V = 0x09, | |
44 | kVK_ANSI_B = 0x0B, | |
45 | kVK_ANSI_Q = 0x0C, | |
46 | kVK_ANSI_W = 0x0D, | |
47 | kVK_ANSI_E = 0x0E, | |
48 | kVK_ANSI_R = 0x0F, | |
49 | kVK_ANSI_Y = 0x10, | |
50 | kVK_ANSI_T = 0x11, | |
51 | kVK_ANSI_1 = 0x12, | |
52 | kVK_ANSI_2 = 0x13, | |
53 | kVK_ANSI_3 = 0x14, | |
54 | kVK_ANSI_4 = 0x15, | |
55 | kVK_ANSI_6 = 0x16, | |
56 | kVK_ANSI_5 = 0x17, | |
57 | kVK_ANSI_Equal = 0x18, | |
58 | kVK_ANSI_9 = 0x19, | |
59 | kVK_ANSI_7 = 0x1A, | |
60 | kVK_ANSI_Minus = 0x1B, | |
61 | kVK_ANSI_8 = 0x1C, | |
62 | kVK_ANSI_0 = 0x1D, | |
63 | kVK_ANSI_RightBracket = 0x1E, | |
64 | kVK_ANSI_O = 0x1F, | |
65 | kVK_ANSI_U = 0x20, | |
66 | kVK_ANSI_LeftBracket = 0x21, | |
67 | kVK_ANSI_I = 0x22, | |
68 | kVK_ANSI_P = 0x23, | |
69 | kVK_ANSI_L = 0x25, | |
70 | kVK_ANSI_J = 0x26, | |
71 | kVK_ANSI_Quote = 0x27, | |
72 | kVK_ANSI_K = 0x28, | |
73 | kVK_ANSI_Semicolon = 0x29, | |
74 | kVK_ANSI_Backslash = 0x2A, | |
75 | kVK_ANSI_Comma = 0x2B, | |
76 | kVK_ANSI_Slash = 0x2C, | |
77 | kVK_ANSI_N = 0x2D, | |
78 | kVK_ANSI_M = 0x2E, | |
79 | kVK_ANSI_Period = 0x2F, | |
80 | kVK_ANSI_Grave = 0x32, | |
81 | kVK_ANSI_KeypadDecimal = 0x41, | |
82 | kVK_ANSI_KeypadMultiply = 0x43, | |
83 | kVK_ANSI_KeypadPlus = 0x45, | |
84 | kVK_ANSI_KeypadClear = 0x47, | |
85 | kVK_ANSI_KeypadDivide = 0x4B, | |
86 | kVK_ANSI_KeypadEnter = 0x4C, | |
87 | kVK_ANSI_KeypadMinus = 0x4E, | |
88 | kVK_ANSI_KeypadEquals = 0x51, | |
89 | kVK_ANSI_Keypad0 = 0x52, | |
90 | kVK_ANSI_Keypad1 = 0x53, | |
91 | kVK_ANSI_Keypad2 = 0x54, | |
92 | kVK_ANSI_Keypad3 = 0x55, | |
93 | kVK_ANSI_Keypad4 = 0x56, | |
94 | kVK_ANSI_Keypad5 = 0x57, | |
95 | kVK_ANSI_Keypad6 = 0x58, | |
96 | kVK_ANSI_Keypad7 = 0x59, | |
97 | kVK_ANSI_Keypad8 = 0x5B, | |
98 | kVK_ANSI_Keypad9 = 0x5C | |
99 | }; | |
100 | ||
101 | // defines for keys that are the same on all layouts | |
102 | ||
103 | enum { | |
104 | kVK_Return = 0x24, | |
105 | kVK_Tab = 0x30, | |
106 | kVK_Space = 0x31, | |
107 | kVK_Delete = 0x33, | |
108 | kVK_Escape = 0x35, | |
109 | kVK_Command = 0x37, | |
110 | kVK_Shift = 0x38, | |
111 | kVK_CapsLock = 0x39, | |
112 | kVK_Option = 0x3A, | |
113 | kVK_Control = 0x3B, | |
114 | kVK_RightShift = 0x3C, | |
115 | kVK_RightOption = 0x3D, | |
116 | kVK_RightControl = 0x3E, | |
117 | kVK_Function = 0x3F, | |
118 | kVK_F17 = 0x40, | |
119 | kVK_VolumeUp = 0x48, | |
120 | kVK_VolumeDown = 0x49, | |
121 | kVK_Mute = 0x4A, | |
122 | kVK_F18 = 0x4F, | |
123 | kVK_F19 = 0x50, | |
124 | kVK_F20 = 0x5A, | |
125 | kVK_F5 = 0x60, | |
126 | kVK_F6 = 0x61, | |
127 | kVK_F7 = 0x62, | |
128 | kVK_F3 = 0x63, | |
129 | kVK_F8 = 0x64, | |
130 | kVK_F9 = 0x65, | |
131 | kVK_F11 = 0x67, | |
132 | kVK_F13 = 0x69, | |
133 | kVK_F16 = 0x6A, | |
134 | kVK_F14 = 0x6B, | |
135 | kVK_F10 = 0x6D, | |
136 | kVK_F12 = 0x6F, | |
137 | kVK_F15 = 0x71, | |
138 | kVK_Help = 0x72, | |
139 | kVK_Home = 0x73, | |
140 | kVK_PageUp = 0x74, | |
141 | kVK_ForwardDelete = 0x75, | |
142 | kVK_F4 = 0x76, | |
143 | kVK_End = 0x77, | |
144 | kVK_F2 = 0x78, | |
145 | kVK_PageDown = 0x79, | |
146 | kVK_F1 = 0x7A, | |
147 | kVK_LeftArrow = 0x7B, | |
148 | kVK_RightArrow = 0x7C, | |
149 | kVK_DownArrow = 0x7D, | |
150 | kVK_UpArrow = 0x7E | |
151 | }; | |
152 | ||
153 | #endif | |
154 | ||
a02a5cfc KO |
155 | CGEventTapLocation tap = kCGSessionEventTap; |
156 | ||
157 | CGEventType CGEventTypeForMouseButton(int button, bool isDown) | |
158 | { | |
571d991b | 159 | switch ( button ) |
a02a5cfc KO |
160 | { |
161 | case wxMOUSE_BTN_LEFT: | |
571d991b | 162 | return isDown ? kCGEventLeftMouseDown : kCGEventLeftMouseUp; |
9b7e0226 | 163 | |
571d991b VZ |
164 | case wxMOUSE_BTN_RIGHT: |
165 | return isDown ? kCGEventRightMouseDown : kCGEventRightMouseUp; | |
9b7e0226 | 166 | |
571d991b VZ |
167 | // All the other buttons use the constant OtherMouseDown but we still |
168 | // want to check for invalid parameters so assert first | |
a02a5cfc | 169 | default: |
571d991b VZ |
170 | wxFAIL_MSG("Unsupported button passed in."); |
171 | // fall back to the only known remaining case | |
172 | ||
173 | case wxMOUSE_BTN_MIDDLE: | |
174 | return isDown ? kCGEventOtherMouseDown : kCGEventOtherMouseUp; | |
a02a5cfc KO |
175 | } |
176 | } | |
177 | ||
571d991b | 178 | CGPoint GetMousePosition() |
a02a5cfc | 179 | { |
571d991b VZ |
180 | int x, y; |
181 | wxGetMousePosition(&x, &y); | |
182 | ||
183 | CGPoint pos; | |
184 | pos.x = x; | |
185 | pos.y = y; | |
186 | ||
187 | return pos; | |
188 | } | |
189 | ||
571d991b VZ |
190 | CGKeyCode wxCharCodeWXToOSX(wxKeyCode code) |
191 | { | |
192 | CGKeyCode keycode; | |
193 | ||
194 | switch (code) | |
a02a5cfc | 195 | { |
571d991b VZ |
196 | case 'a': case 'A': keycode = kVK_ANSI_A; break; |
197 | case 'b': case 'B': keycode = kVK_ANSI_B; break; | |
198 | case 'c': case 'C': keycode = kVK_ANSI_C; break; | |
199 | case 'd': case 'D': keycode = kVK_ANSI_D; break; | |
200 | case 'e': case 'E': keycode = kVK_ANSI_E; break; | |
201 | case 'f': case 'F': keycode = kVK_ANSI_F; break; | |
202 | case 'g': case 'G': keycode = kVK_ANSI_G; break; | |
203 | case 'h': case 'H': keycode = kVK_ANSI_H; break; | |
204 | case 'i': case 'I': keycode = kVK_ANSI_I; break; | |
205 | case 'j': case 'J': keycode = kVK_ANSI_J; break; | |
206 | case 'k': case 'K': keycode = kVK_ANSI_K; break; | |
207 | case 'l': case 'L': keycode = kVK_ANSI_L; break; | |
208 | case 'm': case 'M': keycode = kVK_ANSI_M; break; | |
209 | case 'n': case 'N': keycode = kVK_ANSI_N; break; | |
210 | case 'o': case 'O': keycode = kVK_ANSI_O; break; | |
211 | case 'p': case 'P': keycode = kVK_ANSI_P; break; | |
212 | case 'q': case 'Q': keycode = kVK_ANSI_Q; break; | |
213 | case 'r': case 'R': keycode = kVK_ANSI_R; break; | |
214 | case 's': case 'S': keycode = kVK_ANSI_S; break; | |
215 | case 't': case 'T': keycode = kVK_ANSI_T; break; | |
216 | case 'u': case 'U': keycode = kVK_ANSI_U; break; | |
217 | case 'v': case 'V': keycode = kVK_ANSI_V; break; | |
218 | case 'w': case 'W': keycode = kVK_ANSI_W; break; | |
219 | case 'x': case 'X': keycode = kVK_ANSI_X; break; | |
220 | case 'y': case 'Y': keycode = kVK_ANSI_Y; break; | |
221 | case 'z': case 'Z': keycode = kVK_ANSI_Z; break; | |
222 | ||
223 | case '0': keycode = kVK_ANSI_0; break; | |
224 | case '1': keycode = kVK_ANSI_1; break; | |
225 | case '2': keycode = kVK_ANSI_2; break; | |
226 | case '3': keycode = kVK_ANSI_3; break; | |
227 | case '4': keycode = kVK_ANSI_4; break; | |
228 | case '5': keycode = kVK_ANSI_5; break; | |
229 | case '6': keycode = kVK_ANSI_6; break; | |
230 | case '7': keycode = kVK_ANSI_7; break; | |
231 | case '8': keycode = kVK_ANSI_8; break; | |
232 | case '9': keycode = kVK_ANSI_9; break; | |
233 | ||
234 | case WXK_BACK: keycode = kVK_Delete; break; | |
235 | case WXK_TAB: keycode = kVK_Tab; break; | |
236 | case WXK_RETURN: keycode = kVK_Return; break; | |
237 | case WXK_ESCAPE: keycode = kVK_Escape; break; | |
238 | case WXK_SPACE: keycode = kVK_Space; break; | |
239 | case WXK_DELETE: keycode = kVK_Delete; break; | |
240 | ||
241 | case WXK_SHIFT: keycode = kVK_Shift; break; | |
242 | case WXK_ALT: keycode = kVK_Option; break; | |
243 | case WXK_CONTROL: keycode = kVK_Control; break; | |
244 | case WXK_COMMAND: keycode = kVK_Command; break; | |
245 | ||
246 | case WXK_CAPITAL: keycode = kVK_CapsLock; break; | |
247 | case WXK_END: keycode = kVK_End; break; | |
248 | case WXK_HOME: keycode = kVK_Home; break; | |
249 | case WXK_LEFT: keycode = kVK_LeftArrow; break; | |
250 | case WXK_UP: keycode = kVK_UpArrow; break; | |
251 | case WXK_RIGHT: keycode = kVK_RightArrow; break; | |
252 | case WXK_DOWN: keycode = kVK_DownArrow; break; | |
253 | ||
254 | case WXK_HELP: keycode = kVK_Help; break; | |
255 | ||
256 | ||
257 | case WXK_NUMPAD0: keycode = kVK_ANSI_Keypad0; break; | |
258 | case WXK_NUMPAD1: keycode = kVK_ANSI_Keypad1; break; | |
259 | case WXK_NUMPAD2: keycode = kVK_ANSI_Keypad2; break; | |
260 | case WXK_NUMPAD3: keycode = kVK_ANSI_Keypad3; break; | |
261 | case WXK_NUMPAD4: keycode = kVK_ANSI_Keypad4; break; | |
262 | case WXK_NUMPAD5: keycode = kVK_ANSI_Keypad5; break; | |
263 | case WXK_NUMPAD6: keycode = kVK_ANSI_Keypad6; break; | |
264 | case WXK_NUMPAD7: keycode = kVK_ANSI_Keypad7; break; | |
265 | case WXK_NUMPAD8: keycode = kVK_ANSI_Keypad8; break; | |
266 | case WXK_NUMPAD9: keycode = kVK_ANSI_Keypad9; break; | |
267 | case WXK_F1: keycode = kVK_F1; break; | |
268 | case WXK_F2: keycode = kVK_F2; break; | |
269 | case WXK_F3: keycode = kVK_F3; break; | |
270 | case WXK_F4: keycode = kVK_F4; break; | |
271 | case WXK_F5: keycode = kVK_F5; break; | |
272 | case WXK_F6: keycode = kVK_F6; break; | |
273 | case WXK_F7: keycode = kVK_F7; break; | |
274 | case WXK_F8: keycode = kVK_F8; break; | |
275 | case WXK_F9: keycode = kVK_F9; break; | |
276 | case WXK_F10: keycode = kVK_F10; break; | |
277 | case WXK_F11: keycode = kVK_F11; break; | |
278 | case WXK_F12: keycode = kVK_F12; break; | |
279 | case WXK_F13: keycode = kVK_F13; break; | |
280 | case WXK_F14: keycode = kVK_F14; break; | |
281 | case WXK_F15: keycode = kVK_F15; break; | |
282 | case WXK_F16: keycode = kVK_F16; break; | |
283 | case WXK_F17: keycode = kVK_F17; break; | |
284 | case WXK_F18: keycode = kVK_F18; break; | |
285 | case WXK_F19: keycode = kVK_F19; break; | |
286 | case WXK_F20: keycode = kVK_F20; break; | |
287 | ||
288 | case WXK_PAGEUP: keycode = kVK_PageUp; break; | |
289 | case WXK_PAGEDOWN: keycode = kVK_PageDown; break; | |
290 | ||
291 | case WXK_NUMPAD_DELETE: keycode = kVK_ANSI_KeypadClear; break; | |
292 | case WXK_NUMPAD_EQUAL: keycode = kVK_ANSI_KeypadEquals; break; | |
293 | case WXK_NUMPAD_MULTIPLY: keycode = kVK_ANSI_KeypadMultiply; break; | |
294 | case WXK_NUMPAD_ADD: keycode = kVK_ANSI_KeypadPlus; break; | |
295 | case WXK_NUMPAD_SUBTRACT: keycode = kVK_ANSI_KeypadMinus; break; | |
296 | case WXK_NUMPAD_DECIMAL: keycode = kVK_ANSI_KeypadDecimal; break; | |
297 | case WXK_NUMPAD_DIVIDE: keycode = kVK_ANSI_KeypadDivide; break; | |
298 | ||
453296e7 VZ |
299 | default: |
300 | wxLogDebug( "Unrecognised keycode %d", code ); | |
8f6f3a71 | 301 | keycode = static_cast<CGKeyCode>(-1); |
a02a5cfc | 302 | } |
571d991b VZ |
303 | |
304 | return keycode; | |
a02a5cfc KO |
305 | } |
306 | ||
571d991b VZ |
307 | } // anonymous namespace |
308 | ||
a02a5cfc KO |
309 | bool wxUIActionSimulator::MouseDown(int button) |
310 | { | |
a02a5cfc | 311 | CGEventType type = CGEventTypeForMouseButton(button, true); |
571d991b VZ |
312 | wxCFRef<CGEventRef> event( |
313 | CGEventCreateMouseEvent(NULL, type, GetMousePosition(), button)); | |
314 | ||
315 | if ( !event ) | |
316 | return false; | |
317 | ||
a02a5cfc | 318 | CGEventSetType(event, type); |
571d991b | 319 | CGEventPost(tap, event); |
9b7e0226 | 320 | |
a02a5cfc KO |
321 | return true; |
322 | } | |
323 | ||
324 | bool wxUIActionSimulator::MouseMove(long x, long y) | |
325 | { | |
326 | CGPoint pos; | |
327 | pos.x = x; | |
328 | pos.y = y; | |
571d991b | 329 | |
a02a5cfc | 330 | CGEventType type = kCGEventMouseMoved; |
571d991b VZ |
331 | wxCFRef<CGEventRef> event( |
332 | CGEventCreateMouseEvent(NULL, type, pos, kCGMouseButtonLeft)); | |
9b7e0226 | 333 | |
571d991b VZ |
334 | if ( !event ) |
335 | return false; | |
336 | ||
337 | CGEventSetType(event, type); | |
338 | CGEventPost(tap, event); | |
9b7e0226 | 339 | |
a02a5cfc KO |
340 | return true; |
341 | } | |
342 | ||
343 | bool wxUIActionSimulator::MouseUp(int button) | |
344 | { | |
a02a5cfc | 345 | CGEventType type = CGEventTypeForMouseButton(button, false); |
571d991b VZ |
346 | wxCFRef<CGEventRef> event( |
347 | CGEventCreateMouseEvent(NULL, type, GetMousePosition(), button)); | |
9b7e0226 | 348 | |
571d991b VZ |
349 | if ( !event ) |
350 | return false; | |
351 | ||
352 | CGEventSetType(event, type); | |
353 | CGEventPost(tap, event); | |
a02a5cfc KO |
354 | |
355 | return true; | |
356 | } | |
357 | ||
03bec791 VZ |
358 | bool |
359 | wxUIActionSimulator::DoKey(int keycode, int WXUNUSED(modifiers), bool isDown) | |
a02a5cfc | 360 | { |
571d991b | 361 | CGKeyCode cgcode = wxCharCodeWXToOSX((wxKeyCode)keycode); |
571d991b | 362 | |
37141214 VZ |
363 | wxCFRef<CGEventRef> |
364 | event(CGEventCreateKeyboardEvent(NULL, cgcode, isDown)); | |
365 | if ( !event ) | |
366 | return false; | |
9b7e0226 | 367 | |
37141214 | 368 | CGEventPost(kCGHIDEventTap, event); |
a02a5cfc KO |
369 | return true; |
370 | } | |
371 | ||
9b7e0226 | 372 | #endif // wxUSE_UIACTIONSIMULATOR |
a02a5cfc | 373 |