376 lines
11 KiB
C++
376 lines
11 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// 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"
|
|
|
|
|
|
#if wxUSE_UIACTIONSIMULATOR
|
|
|
|
#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"
|
|
|
|
#ifdef __WXGTK__
|
|
#include "wx/stopwatch.h"
|
|
#endif
|
|
|
|
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() wxOVERRIDE;
|
|
virtual void tearDown() wxOVERRIDE;
|
|
|
|
private:
|
|
CPPUNIT_TEST_SUITE( KeyboardEventTestCase );
|
|
WXUISIM_TEST( NormalLetter );
|
|
WXUISIM_TEST( NormalSpecial );
|
|
WXUISIM_TEST( CtrlLetter );
|
|
WXUISIM_TEST( CtrlSpecial );
|
|
WXUISIM_TEST( ShiftLetter );
|
|
WXUISIM_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());
|
|
wxYield();
|
|
m_win->SetFocus();
|
|
|
|
#ifdef __WXGTK__
|
|
for ( wxStopWatch sw; sw.Time() < 10; )
|
|
#endif
|
|
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
|