add more high-level event concepts, fixing native button number
[wxWidgets.git] / src / osx / uiaction_osx.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/uiaction_osx.cpp
3 // Purpose: wxUIActionSimulator implementation
4 // Author: Kevin Ollivier, Steven Lamerton, Vadim Zeitlin
5 // Modified by:
6 // Created: 2010-03-06
7 // RCS-ID: $Id$
8 // Copyright: (c) Kevin Ollivier
9 // (c) 2010 Steven Lamerton
10 // (c) 2010 Vadim Zeitlin
11 // Licence: wxWindows licence
12 /////////////////////////////////////////////////////////////////////////////
13
14 #include "wx/wxprec.h"
15
16 #ifndef WX_PRECOMP
17 #include "wx/object.h"
18 #endif
19
20 #if wxUSE_UIACTIONSIMULATOR
21
22 #include "wx/uiaction.h"
23
24 #include "wx/log.h"
25
26 #include "wx/osx/private.h"
27 #include "wx/osx/core/cfref.h"
28
29 #include "wx/evtloop.h"
30
31 namespace
32 {
33
34 CGEventTapLocation tap = kCGSessionEventTap;
35
36 CGEventType CGEventTypeForMouseButton(int button, bool isDown)
37 {
38 switch ( button )
39 {
40 case wxMOUSE_BTN_LEFT:
41 return isDown ? kCGEventLeftMouseDown : kCGEventLeftMouseUp;
42
43 case wxMOUSE_BTN_RIGHT:
44 return isDown ? kCGEventRightMouseDown : kCGEventRightMouseUp;
45
46 // All the other buttons use the constant OtherMouseDown but we still
47 // want to check for invalid parameters so assert first
48 default:
49 wxFAIL_MSG("Unsupported button passed in.");
50 // fall back to the only known remaining case
51
52 case wxMOUSE_BTN_MIDDLE:
53 return isDown ? kCGEventOtherMouseDown : kCGEventOtherMouseUp;
54 }
55 }
56
57 CGEventType CGEventTypeForMouseDrag(int button)
58 {
59 switch ( button )
60 {
61 case wxMOUSE_BTN_LEFT:
62 return kCGEventLeftMouseDragged;
63 break;
64
65 case wxMOUSE_BTN_RIGHT:
66 return kCGEventRightMouseDragged;
67 break;
68
69 // All the other buttons use the constant OtherMouseDown but we still
70 // want to check for invalid parameters so assert first
71 default:
72 wxFAIL_MSG("Unsupported button passed in.");
73 // fall back to the only known remaining case
74
75 case wxMOUSE_BTN_MIDDLE:
76 return kCGEventOtherMouseDragged;
77 break;
78 }
79
80 }
81
82 CGMouseButton CGButtonForMouseButton(int button)
83 {
84 switch ( button )
85 {
86 case wxMOUSE_BTN_LEFT:
87 return kCGMouseButtonLeft;
88
89 case wxMOUSE_BTN_RIGHT:
90 return kCGMouseButtonRight;
91
92 // All the other buttons use the constant OtherMouseDown but we still
93 // want to check for invalid parameters so assert first
94 default:
95 wxFAIL_MSG("Unsupported button passed in.");
96 // fall back to the only known remaining case
97
98 case wxMOUSE_BTN_MIDDLE:
99 return kCGMouseButtonCenter;
100 }
101 }
102
103 CGPoint GetMousePosition()
104 {
105 int x, y;
106 wxGetMousePosition(&x, &y);
107
108 CGPoint pos;
109 pos.x = x;
110 pos.y = y;
111
112 return pos;
113 }
114
115 } // anonymous namespace
116
117 bool wxUIActionSimulator::MouseDown(int button)
118 {
119 CGEventType type = CGEventTypeForMouseButton(button, true);
120 wxCFRef<CGEventRef> event(
121 CGEventCreateMouseEvent(NULL, type, GetMousePosition(), CGButtonForMouseButton(button)));
122
123 if ( !event )
124 return false;
125
126 CGEventSetType(event, type);
127 CGEventPost(tap, event);
128 wxCFEventLoop* loop = dynamic_cast<wxCFEventLoop*>(wxEventLoop::GetActive());
129 if (loop)
130 loop->SetShouldWaitForEvent(true);
131
132 return true;
133 }
134
135 bool wxUIActionSimulator::MouseMove(long x, long y)
136 {
137 CGPoint pos;
138 pos.x = x;
139 pos.y = y;
140
141 CGEventType type = kCGEventMouseMoved;
142 wxCFRef<CGEventRef> event(
143 CGEventCreateMouseEvent(NULL, type, pos, kCGMouseButtonLeft));
144
145 if ( !event )
146 return false;
147
148 CGEventSetType(event, type);
149 CGEventPost(tap, event);
150
151 wxCFEventLoop* loop = dynamic_cast<wxCFEventLoop*>(wxEventLoop::GetActive());
152 if (loop)
153 loop->SetShouldWaitForEvent(true);
154
155 return true;
156 }
157
158 bool wxUIActionSimulator::MouseUp(int button)
159 {
160 CGEventType type = CGEventTypeForMouseButton(button, false);
161 wxCFRef<CGEventRef> event(
162 CGEventCreateMouseEvent(NULL, type, GetMousePosition(), CGButtonForMouseButton(button)));
163
164 if ( !event )
165 return false;
166
167 CGEventSetType(event, type);
168 CGEventPost(tap, event);
169 wxCFEventLoop* loop = dynamic_cast<wxCFEventLoop*>(wxEventLoop::GetActive());
170 if (loop)
171 loop->SetShouldWaitForEvent(true);
172
173 return true;
174 }
175
176 bool wxUIActionSimulator::MouseDblClick(int button)
177 {
178 CGEventType downtype = CGEventTypeForMouseButton(button, true);
179 CGEventType uptype = CGEventTypeForMouseButton(button, false);
180 wxCFRef<CGEventRef> event(
181 CGEventCreateMouseEvent(NULL, downtype, GetMousePosition(), CGButtonForMouseButton(button)));
182
183 if ( !event )
184 return false;
185
186 CGEventSetType(event,downtype);
187 CGEventPost(tap, event);
188
189 CGEventSetType(event, uptype);
190 CGEventPost(tap, event);
191
192 CGEventSetIntegerValueField(event, kCGMouseEventClickState, 2);
193 CGEventSetType(event, downtype);
194 CGEventPost(tap, event);
195
196 CGEventSetType(event, uptype);
197 CGEventPost(tap, event);
198 wxCFEventLoop* loop = dynamic_cast<wxCFEventLoop*>(wxEventLoop::GetActive());
199 if (loop)
200 loop->SetShouldWaitForEvent(true);
201
202 return true;
203 }
204
205 bool wxUIActionSimulator::MouseClickAndDragTo(long x, long y, int button)
206 {
207 CGEventType downtype = CGEventTypeForMouseButton(button, true);
208 CGEventType uptype = CGEventTypeForMouseButton(button, false);
209 CGEventType dragtype = CGEventTypeForMouseDrag(button) ;
210
211 wxCFRef<CGEventRef> event(
212 CGEventCreateMouseEvent(NULL, downtype, GetMousePosition(), CGButtonForMouseButton(button)));
213
214 if ( !event )
215 return false;
216
217 CGEventSetType(event,downtype);
218 CGEventPost(tap, event);
219
220 CGPoint pos;
221 pos.x = x;
222 pos.y = y;
223
224 CGEventSetType(event, dragtype);
225 CGEventSetLocation(event,pos);
226 CGEventPost(tap, event);
227
228 CGEventSetType(event, uptype);
229 CGEventPost(tap, event);
230 wxCFEventLoop* loop = dynamic_cast<wxCFEventLoop*>(wxEventLoop::GetActive());
231 if (loop)
232 loop->SetShouldWaitForEvent(true);
233
234 return true;
235 }
236
237 bool
238 wxUIActionSimulator::DoKey(int keycode, int WXUNUSED(modifiers), bool isDown)
239 {
240 CGKeyCode cgcode = wxCharCodeWXToOSX((wxKeyCode)keycode);
241
242 wxCFRef<CGEventRef>
243 event(CGEventCreateKeyboardEvent(NULL, cgcode, isDown));
244 if ( !event )
245 return false;
246
247 CGEventPost(kCGHIDEventTap, event);
248 wxCFEventLoop* loop = dynamic_cast<wxCFEventLoop*>(wxEventLoop::GetActive());
249 if (loop)
250 loop->SetShouldWaitForEvent(true);
251
252 return true;
253 }
254
255 #endif // wxUSE_UIACTIONSIMULATOR
256