The rounded corners look really dumb at this size.
[wxWidgets.git] / tests / events / keyboard.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: tests/events/keyboard.cpp
3 // Purpose: Test keyboard events
4 // Author: Vadim Zeitlin
5 // Created: 2010-09-05
6 // Copyright: (c) 2010 Vadim Zeitlin <vadim@wxwidgets.org>
7 ///////////////////////////////////////////////////////////////////////////////
8
9 // ----------------------------------------------------------------------------
10 // headers
11 // ----------------------------------------------------------------------------
12
13 #include "testprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 // FIXME: As all the other tests involving wxUIActionSimulator, this one is
20 // broken under OS X, the test window siply never gets any events.
21 #if wxUSE_UIACTIONSIMULATOR && !defined(__WXOSX__)
22
23 #ifndef WX_PRECOMP
24 #include "wx/app.h"
25 #include "wx/event.h"
26 #include "wx/window.h"
27 #endif // WX_PRECOMP
28
29 #include "wx/uiaction.h"
30 #include "wx/vector.h"
31
32 namespace
33 {
34
35 // ----------------------------------------------------------------------------
36 // test window verifying the event generation
37 // ----------------------------------------------------------------------------
38
39 class KeyboardTestWindow : public wxWindow
40 {
41 public:
42 KeyboardTestWindow(wxWindow *parent)
43 : wxWindow(parent, wxID_ANY, wxPoint(0, 0), parent->GetClientSize())
44 {
45 Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(KeyboardTestWindow::OnKeyDown));
46 Connect(wxEVT_CHAR, wxKeyEventHandler(KeyboardTestWindow::OnChar));
47 Connect(wxEVT_KEY_UP, wxKeyEventHandler(KeyboardTestWindow::OnKeyUp));
48 }
49
50 unsigned GetKeyDownCount() const { return m_keyDownEvents.size(); }
51 unsigned GetCharCount() const { return m_charEvents.size(); }
52 unsigned GetKeyUpCount() const { return m_keyUpEvents.size(); }
53
54 const wxKeyEvent& GetKeyDownEvent(unsigned n = 0) const
55 {
56 return m_keyDownEvents[n];
57 }
58 const wxKeyEvent& GetCharEvent(unsigned n = 0) const
59 {
60 return m_charEvents[n];
61 }
62 const wxKeyEvent& GetKeyUpEvent(unsigned n = 0) const
63 {
64 return m_keyUpEvents[n];
65 }
66
67 void ClearEvents()
68 {
69 m_keyDownEvents =
70 m_charEvents =
71 m_keyUpEvents = wxVector<wxKeyEvent>();
72 }
73
74 private:
75 void OnKeyDown(wxKeyEvent& event)
76 {
77 m_keyDownEvents.push_back(event);
78 event.Skip();
79 }
80
81 void OnChar(wxKeyEvent& event)
82 {
83 m_charEvents.push_back(event);
84 event.Skip();
85 }
86
87 void OnKeyUp(wxKeyEvent& event)
88 {
89 m_keyUpEvents.push_back(event);
90 event.Skip();
91 }
92
93 wxVector<wxKeyEvent> m_keyDownEvents,
94 m_charEvents,
95 m_keyUpEvents;
96
97
98 wxDECLARE_NO_COPY_CLASS(KeyboardTestWindow);
99 };
100
101 // Object describing the (main fields of) keyboard event.
102 struct KeyDesc
103 {
104 KeyDesc(int keycode, int mods = 0)
105 : m_keycode(keycode),
106 m_mods(mods)
107 {
108 }
109
110 int m_keycode;
111 int m_mods;
112 };
113
114 // Helper for ModKeyDown().
115 int GetModForKey(int keycode)
116 {
117 switch ( keycode )
118 {
119 case WXK_CONTROL: return wxMOD_CONTROL;
120 case WXK_SHIFT: return wxMOD_SHIFT;
121 case WXK_ALT: return wxMOD_ALT;
122 default:
123 wxFAIL_MSG( "Unknown modifier key" );
124 }
125
126 return wxMOD_NONE;
127 }
128
129 // Helper function to allow writing just ModKeyDown(WXK_CONTROL) instead of
130 // more verbose KeyDesc(WXK_CONTROL, wxMOD_CONTROL).
131 KeyDesc ModKeyDown(int keycode)
132 {
133 return KeyDesc(keycode, GetModForKey(keycode));
134 }
135
136 // Another helper provided for symmetry with ModKeyDown() only.
137 KeyDesc ModKeyUp(int keycode)
138 {
139 return KeyDesc(keycode);
140 }
141
142 // Verify that the event object corresponds to our idea of what it should be.
143 void TestEvent(int line, const wxKeyEvent& ev, const KeyDesc& desc)
144 {
145 // Construct the message we'll display if an assert fails.
146 std::string msg;
147 const wxEventType t = ev.GetEventType();
148 if ( t == wxEVT_KEY_DOWN )
149 msg = "key down";
150 else if ( t == wxEVT_CHAR )
151 msg = "char";
152 else if ( t == wxEVT_KEY_UP )
153 msg = "key up";
154 else
155 CPPUNIT_FAIL( "unknown event type" );
156
157 msg += " event at line ";
158 msg += wxString::Format("%d", line).mb_str();
159
160
161 CPPUNIT_ASSERT_EQUAL_MESSAGE( "wrong key code in " + msg,
162 desc.m_keycode,
163 ev.GetKeyCode() );
164
165 #if wxUSE_UNICODE
166 if ( desc.m_keycode < WXK_START )
167 {
168 // For Latin-1 our key code is the same as Unicode character value.
169 CPPUNIT_ASSERT_EQUAL_MESSAGE( "wrong Unicode key in " + msg,
170 (char)desc.m_keycode,
171 (char)ev.GetUnicodeKey() );
172 }
173 else // Special key
174 {
175 // Key codes above WXK_START don't correspond to printable characters.
176 CPPUNIT_ASSERT_EQUAL_MESSAGE( "wrong non-zero Unicode key in " + msg,
177 0,
178 (int)ev.GetUnicodeKey() );
179 }
180 #endif // wxUSE_UNICODE
181
182 CPPUNIT_ASSERT_EQUAL_MESSAGE( "wrong modifiers in " + msg,
183 desc.m_mods,
184 ev.GetModifiers() );
185 }
186
187 // Call TestEvent() passing it the line number from where it was called: this
188 // is useful for interpreting the assert failure messages.
189 #define ASSERT_KEY_EVENT_IS( ev, desc ) TestEvent(__LINE__, ev, desc)
190
191 } // anonymous namespace
192
193 // --------------------------------------------------------------------------
194 // test class
195 // --------------------------------------------------------------------------
196
197 class KeyboardEventTestCase : public CppUnit::TestCase
198 {
199 public:
200 KeyboardEventTestCase() {}
201
202 virtual void setUp();
203 virtual void tearDown();
204
205 private:
206 CPPUNIT_TEST_SUITE( KeyboardEventTestCase );
207 CPPUNIT_TEST( NormalLetter );
208 CPPUNIT_TEST( NormalSpecial );
209 CPPUNIT_TEST( CtrlLetter );
210 CPPUNIT_TEST( CtrlSpecial );
211 CPPUNIT_TEST( ShiftLetter );
212 CPPUNIT_TEST( ShiftSpecial );
213 CPPUNIT_TEST_SUITE_END();
214
215 void NormalLetter();
216 void NormalSpecial();
217 void CtrlLetter();
218 void CtrlSpecial();
219 void ShiftLetter();
220 void ShiftSpecial();
221
222 KeyboardTestWindow *m_win;
223
224 wxDECLARE_NO_COPY_CLASS(KeyboardEventTestCase);
225 };
226
227 wxREGISTER_UNIT_TEST(KeyboardEvent);
228
229 void KeyboardEventTestCase::setUp()
230 {
231 m_win = new KeyboardTestWindow(wxTheApp->GetTopWindow());
232 m_win->SetFocus();
233 wxYield(); // needed to show the new window
234
235 // The window might get some key up events when it's being shown if the key
236 // was pressed when the program was started and released after the window
237 // was shown, e.g. this does happen in practice when launching the test
238 // from command line. Simply discard all the spurious events so far.
239 m_win->ClearEvents();
240 }
241
242 void KeyboardEventTestCase::tearDown()
243 {
244 m_win->Destroy();
245 }
246
247 void KeyboardEventTestCase::NormalLetter()
248 {
249 wxUIActionSimulator sim;
250 sim.Char('a');
251 wxYield();
252
253 CPPUNIT_ASSERT_EQUAL( 1, m_win->GetKeyDownCount() );
254 ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(), 'A' );
255
256 CPPUNIT_ASSERT_EQUAL( 1, m_win->GetCharCount() );
257 ASSERT_KEY_EVENT_IS( m_win->GetCharEvent(), 'a' );
258
259 CPPUNIT_ASSERT_EQUAL( 1, m_win->GetKeyUpCount() );
260 ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(), 'A' );
261 }
262
263 void KeyboardEventTestCase::NormalSpecial()
264 {
265 wxUIActionSimulator sim;
266 sim.Char(WXK_END);
267 wxYield();
268
269 CPPUNIT_ASSERT_EQUAL( 1, m_win->GetKeyDownCount() );
270 ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(), WXK_END );
271
272 CPPUNIT_ASSERT_EQUAL( 1, m_win->GetCharCount() );
273 ASSERT_KEY_EVENT_IS( m_win->GetCharEvent(), WXK_END );
274
275 CPPUNIT_ASSERT_EQUAL( 1, m_win->GetKeyUpCount() );
276 ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(), WXK_END );
277 }
278
279 void KeyboardEventTestCase::CtrlLetter()
280 {
281 wxUIActionSimulator sim;
282 sim.Char('z', wxMOD_CONTROL);
283 wxYield();
284
285 CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyDownCount() );
286 ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(0),
287 ModKeyDown(WXK_CONTROL) );
288 ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(1),
289 KeyDesc('Z', wxMOD_CONTROL) );
290
291 CPPUNIT_ASSERT_EQUAL( 1, m_win->GetCharCount() );
292 ASSERT_KEY_EVENT_IS( m_win->GetCharEvent(),
293 KeyDesc('\x1a', wxMOD_CONTROL) );
294
295 CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyUpCount() );
296 ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(0),
297 KeyDesc('Z', wxMOD_CONTROL) );
298 ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(1),
299 ModKeyUp(WXK_CONTROL) );
300 }
301
302 void KeyboardEventTestCase::CtrlSpecial()
303 {
304 wxUIActionSimulator sim;
305 sim.Char(WXK_PAGEUP, wxMOD_CONTROL);
306 wxYield();
307
308 CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyDownCount() );
309 ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(0),
310 ModKeyDown(WXK_CONTROL) );
311 ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(1),
312 KeyDesc(WXK_PAGEUP, wxMOD_CONTROL) );
313
314 CPPUNIT_ASSERT_EQUAL( 1, m_win->GetCharCount() );
315 ASSERT_KEY_EVENT_IS( m_win->GetCharEvent(),
316 KeyDesc(WXK_PAGEUP, wxMOD_CONTROL) );
317
318 CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyUpCount() );
319 ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(0),
320 KeyDesc(WXK_PAGEUP, wxMOD_CONTROL) );
321 ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(1),
322 ModKeyUp(WXK_CONTROL) );
323 }
324
325 void KeyboardEventTestCase::ShiftLetter()
326 {
327 wxUIActionSimulator sim;
328 sim.Char('Q', wxMOD_SHIFT);
329 wxYield();
330
331 CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyDownCount() );
332 ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(0),
333 ModKeyDown(WXK_SHIFT) );
334 ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(1),
335 KeyDesc('Q', wxMOD_SHIFT) );
336
337 CPPUNIT_ASSERT_EQUAL( 1, m_win->GetCharCount() );
338 ASSERT_KEY_EVENT_IS( m_win->GetCharEvent(),
339 KeyDesc('Q', wxMOD_SHIFT) );
340
341 CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyUpCount() );
342 ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(0),
343 KeyDesc('Q', wxMOD_SHIFT) );
344 ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(1),
345 ModKeyUp(WXK_SHIFT) );
346 }
347
348 void KeyboardEventTestCase::ShiftSpecial()
349 {
350 wxUIActionSimulator sim;
351 sim.Char(WXK_F3, wxMOD_SHIFT);
352 wxYield();
353
354 CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyDownCount() );
355 ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(0),
356 ModKeyDown(WXK_SHIFT) );
357 ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(1),
358 KeyDesc(WXK_F3, wxMOD_SHIFT) );
359
360 CPPUNIT_ASSERT_EQUAL( 1, m_win->GetCharCount() );
361 ASSERT_KEY_EVENT_IS( m_win->GetCharEvent(),
362 KeyDesc(WXK_F3, wxMOD_SHIFT) );
363
364 CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyUpCount() );
365 ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(0),
366 KeyDesc(WXK_F3, wxMOD_SHIFT) );
367 ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(1),
368 ModKeyUp(WXK_SHIFT) );
369 }
370
371 #endif // wxUSE_UIACTIONSIMULATOR