File: keyboard.cpp

package info (click to toggle)
wxwidgets3.0 3.0.5.1%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 120,464 kB
  • sloc: cpp: 896,633; makefile: 52,303; ansic: 21,971; sh: 5,713; python: 2,940; xml: 1,534; perl: 264; javascript: 33
file content (371 lines) | stat: -rw-r--r-- 11,215 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
///////////////////////////////////////////////////////////////////////////////
// Name:        tests/events/keyboard.cpp
// Purpose:     Test keyboard events
// Author:      Vadim Zeitlin
// Created:     2010-09-05
// Copyright:   (c) 2010 Vadim Zeitlin <vadim@wxwidgets.org>
///////////////////////////////////////////////////////////////////////////////

// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------

#include "testprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

// FIXME: As all the other tests involving wxUIActionSimulator, this one is
//        broken under OS X, the test window siply never gets any events.
#if wxUSE_UIACTIONSIMULATOR && !defined(__WXOSX__)

#ifndef WX_PRECOMP
    #include "wx/app.h"
    #include "wx/event.h"
    #include "wx/window.h"
#endif // WX_PRECOMP

#include "wx/uiaction.h"
#include "wx/vector.h"

namespace
{

// ----------------------------------------------------------------------------
// test window verifying the event generation
// ----------------------------------------------------------------------------

class KeyboardTestWindow : public wxWindow
{
public:
    KeyboardTestWindow(wxWindow *parent)
        : wxWindow(parent, wxID_ANY, wxPoint(0, 0), parent->GetClientSize())
    {
        Connect(wxEVT_KEY_DOWN, wxKeyEventHandler(KeyboardTestWindow::OnKeyDown));
        Connect(wxEVT_CHAR, wxKeyEventHandler(KeyboardTestWindow::OnChar));
        Connect(wxEVT_KEY_UP, wxKeyEventHandler(KeyboardTestWindow::OnKeyUp));
    }

    unsigned GetKeyDownCount() const { return m_keyDownEvents.size(); }
    unsigned GetCharCount() const { return m_charEvents.size(); }
    unsigned GetKeyUpCount() const { return m_keyUpEvents.size(); }

    const wxKeyEvent& GetKeyDownEvent(unsigned n = 0) const
    {
        return m_keyDownEvents[n];
    }
    const wxKeyEvent& GetCharEvent(unsigned n = 0) const
    {
        return m_charEvents[n];
    }
    const wxKeyEvent& GetKeyUpEvent(unsigned n = 0) const
    {
        return m_keyUpEvents[n];
    }

    void ClearEvents()
    {
        m_keyDownEvents =
        m_charEvents =
        m_keyUpEvents = wxVector<wxKeyEvent>();
    }

private:
    void OnKeyDown(wxKeyEvent& event)
    {
        m_keyDownEvents.push_back(event);
        event.Skip();
    }

    void OnChar(wxKeyEvent& event)
    {
        m_charEvents.push_back(event);
        event.Skip();
    }

    void OnKeyUp(wxKeyEvent& event)
    {
        m_keyUpEvents.push_back(event);
        event.Skip();
    }

    wxVector<wxKeyEvent> m_keyDownEvents,
                         m_charEvents,
                         m_keyUpEvents;


    wxDECLARE_NO_COPY_CLASS(KeyboardTestWindow);
};

// Object describing the (main fields of) keyboard event.
struct KeyDesc
{
    KeyDesc(int keycode, int mods = 0)
        : m_keycode(keycode),
          m_mods(mods)
    {
    }

    int m_keycode;
    int m_mods;
};

// Helper for ModKeyDown().
int GetModForKey(int keycode)
{
    switch ( keycode )
    {
        case WXK_CONTROL:   return wxMOD_CONTROL;
        case WXK_SHIFT:     return wxMOD_SHIFT;
        case WXK_ALT:       return wxMOD_ALT;
        default:
            wxFAIL_MSG( "Unknown modifier key" );
    }

    return wxMOD_NONE;
}

// Helper function to allow writing just ModKeyDown(WXK_CONTROL) instead of
// more verbose KeyDesc(WXK_CONTROL, wxMOD_CONTROL).
KeyDesc ModKeyDown(int keycode)
{
    return KeyDesc(keycode, GetModForKey(keycode));
}

// Another helper provided for symmetry with ModKeyDown() only.
KeyDesc ModKeyUp(int keycode)
{
    return KeyDesc(keycode);
}

// Verify that the event object corresponds to our idea of what it should be.
void TestEvent(int line, const wxKeyEvent& ev, const KeyDesc& desc)
{
    // Construct the message we'll display if an assert fails.
    std::string msg;
    const wxEventType t = ev.GetEventType();
    if ( t == wxEVT_KEY_DOWN )
        msg = "key down";
    else if ( t == wxEVT_CHAR )
        msg = "char";
    else if ( t == wxEVT_KEY_UP )
        msg = "key up";
    else
        CPPUNIT_FAIL( "unknown event type" );

    msg += " event at line ";
    msg += wxString::Format("%d", line).mb_str();


    CPPUNIT_ASSERT_EQUAL_MESSAGE( "wrong key code in " + msg,
                                  desc.m_keycode,
                                  ev.GetKeyCode() );

#if wxUSE_UNICODE
    if ( desc.m_keycode < WXK_START )
    {
        // For Latin-1 our key code is the same as Unicode character value.
        CPPUNIT_ASSERT_EQUAL_MESSAGE( "wrong Unicode key in " + msg,
                                      (char)desc.m_keycode,
                                      (char)ev.GetUnicodeKey() );
    }
    else // Special key
    {
        // Key codes above WXK_START don't correspond to printable characters.
        CPPUNIT_ASSERT_EQUAL_MESSAGE( "wrong non-zero Unicode key in " + msg,
                                      0,
                                      (int)ev.GetUnicodeKey() );
    }
#endif // wxUSE_UNICODE

    CPPUNIT_ASSERT_EQUAL_MESSAGE( "wrong modifiers in " + msg,
                                  desc.m_mods,
                                  ev.GetModifiers() );
}

// Call TestEvent() passing it the line number from where it was called: this
// is useful for interpreting the assert failure messages.
#define ASSERT_KEY_EVENT_IS( ev, desc ) TestEvent(__LINE__, ev, desc)

} // anonymous namespace

// --------------------------------------------------------------------------
// test class
// --------------------------------------------------------------------------

class KeyboardEventTestCase : public CppUnit::TestCase
{
public:
    KeyboardEventTestCase() {}

    virtual void setUp();
    virtual void tearDown();

private:
    CPPUNIT_TEST_SUITE( KeyboardEventTestCase );
        CPPUNIT_TEST( NormalLetter );
        CPPUNIT_TEST( NormalSpecial );
        CPPUNIT_TEST( CtrlLetter );
        CPPUNIT_TEST( CtrlSpecial );
        CPPUNIT_TEST( ShiftLetter );
        CPPUNIT_TEST( ShiftSpecial );
    CPPUNIT_TEST_SUITE_END();

    void NormalLetter();
    void NormalSpecial();
    void CtrlLetter();
    void CtrlSpecial();
    void ShiftLetter();
    void ShiftSpecial();

    KeyboardTestWindow *m_win;

    wxDECLARE_NO_COPY_CLASS(KeyboardEventTestCase);
};

wxREGISTER_UNIT_TEST(KeyboardEvent);

void KeyboardEventTestCase::setUp()
{
    m_win = new KeyboardTestWindow(wxTheApp->GetTopWindow());
    m_win->SetFocus();
    wxYield(); // needed to show the new window

    // The window might get some key up events when it's being shown if the key
    // was pressed when the program was started and released after the window
    // was shown, e.g. this does happen in practice when launching the test
    // from command line. Simply discard all the spurious events so far.
    m_win->ClearEvents();
}

void KeyboardEventTestCase::tearDown()
{
    m_win->Destroy();
}

void KeyboardEventTestCase::NormalLetter()
{
    wxUIActionSimulator sim;
    sim.Char('a');
    wxYield();

    CPPUNIT_ASSERT_EQUAL( 1, m_win->GetKeyDownCount() );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(), 'A' );

    CPPUNIT_ASSERT_EQUAL( 1, m_win->GetCharCount() );
    ASSERT_KEY_EVENT_IS( m_win->GetCharEvent(), 'a' );

    CPPUNIT_ASSERT_EQUAL( 1, m_win->GetKeyUpCount() );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(), 'A' );
}

void KeyboardEventTestCase::NormalSpecial()
{
    wxUIActionSimulator sim;
    sim.Char(WXK_END);
    wxYield();

    CPPUNIT_ASSERT_EQUAL( 1, m_win->GetKeyDownCount() );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(), WXK_END );

    CPPUNIT_ASSERT_EQUAL( 1, m_win->GetCharCount() );
    ASSERT_KEY_EVENT_IS( m_win->GetCharEvent(), WXK_END );

    CPPUNIT_ASSERT_EQUAL( 1, m_win->GetKeyUpCount() );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(), WXK_END );
}

void KeyboardEventTestCase::CtrlLetter()
{
    wxUIActionSimulator sim;
    sim.Char('z', wxMOD_CONTROL);
    wxYield();

    CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyDownCount() );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(0),
                         ModKeyDown(WXK_CONTROL) );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(1),
                         KeyDesc('Z', wxMOD_CONTROL) );

    CPPUNIT_ASSERT_EQUAL( 1, m_win->GetCharCount() );
    ASSERT_KEY_EVENT_IS( m_win->GetCharEvent(),
                         KeyDesc('\x1a', wxMOD_CONTROL) );

    CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyUpCount() );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(0),
                         KeyDesc('Z', wxMOD_CONTROL) );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(1),
                         ModKeyUp(WXK_CONTROL) );
}

void KeyboardEventTestCase::CtrlSpecial()
{
    wxUIActionSimulator sim;
    sim.Char(WXK_PAGEUP, wxMOD_CONTROL);
    wxYield();

    CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyDownCount() );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(0),
                         ModKeyDown(WXK_CONTROL) );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(1),
                         KeyDesc(WXK_PAGEUP, wxMOD_CONTROL) );

    CPPUNIT_ASSERT_EQUAL( 1, m_win->GetCharCount() );
    ASSERT_KEY_EVENT_IS( m_win->GetCharEvent(),
                         KeyDesc(WXK_PAGEUP, wxMOD_CONTROL) );

    CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyUpCount() );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(0),
                         KeyDesc(WXK_PAGEUP, wxMOD_CONTROL) );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(1),
                         ModKeyUp(WXK_CONTROL) );
}

void KeyboardEventTestCase::ShiftLetter()
{
    wxUIActionSimulator sim;
    sim.Char('Q', wxMOD_SHIFT);
    wxYield();

    CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyDownCount() );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(0),
                         ModKeyDown(WXK_SHIFT) );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(1),
                         KeyDesc('Q', wxMOD_SHIFT) );

    CPPUNIT_ASSERT_EQUAL( 1, m_win->GetCharCount() );
    ASSERT_KEY_EVENT_IS( m_win->GetCharEvent(),
                         KeyDesc('Q', wxMOD_SHIFT) );

    CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyUpCount() );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(0),
                         KeyDesc('Q', wxMOD_SHIFT) );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(1),
                         ModKeyUp(WXK_SHIFT) );
}

void KeyboardEventTestCase::ShiftSpecial()
{
    wxUIActionSimulator sim;
    sim.Char(WXK_F3, wxMOD_SHIFT);
    wxYield();

    CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyDownCount() );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(0),
                         ModKeyDown(WXK_SHIFT) );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyDownEvent(1),
                         KeyDesc(WXK_F3, wxMOD_SHIFT) );

    CPPUNIT_ASSERT_EQUAL( 1, m_win->GetCharCount() );
    ASSERT_KEY_EVENT_IS( m_win->GetCharEvent(),
                         KeyDesc(WXK_F3, wxMOD_SHIFT) );

    CPPUNIT_ASSERT_EQUAL( 2, m_win->GetKeyUpCount() );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(0),
                         KeyDesc(WXK_F3, wxMOD_SHIFT) );
    ASSERT_KEY_EVENT_IS( m_win->GetKeyUpEvent(1),
                         ModKeyUp(WXK_SHIFT) );
}

#endif // wxUSE_UIACTIONSIMULATOR