initial commit
Signed-off-by: Peter Siegmund <mars3142@noreply.mars3142.dev>
This commit is contained in:
68
libs/wxWidgets-3.3.1/tests/events/clone.cpp
Normal file
68
libs/wxWidgets-3.3.1/tests/events/clone.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: tests/events/clone.cpp
|
||||
// Purpose: Test wxEvent::Clone() implementation by all event classes
|
||||
// Author: Vadim Zeitlin, based on the code by Francesco Montorsi
|
||||
// Created: 2009-03-22
|
||||
// Copyright: (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "testprec.h"
|
||||
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/event.h"
|
||||
#include "wx/timer.h"
|
||||
#endif // WX_PRECOMP
|
||||
|
||||
TEST_CASE("EventClone", "[wxEvent][clone]")
|
||||
{
|
||||
// Dummy timer needed just to create a wxTimerEvent.
|
||||
wxTimer dummyTimer;
|
||||
|
||||
// check if event classes implement Clone() correctly
|
||||
// NOTE: the check is done against _all_ event classes which are linked to
|
||||
// the executable currently running, which are not necessarily all
|
||||
// wxWidgets event classes.
|
||||
const wxClassInfo *ci = wxClassInfo::GetFirst();
|
||||
for (; ci; ci = ci->GetNext())
|
||||
{
|
||||
wxString cn = wxString(ci->GetClassName());
|
||||
|
||||
// is this class derived from wxEvent?
|
||||
if ( !ci->IsKindOf(CLASSINFO(wxEvent)) ||
|
||||
cn == "wxEvent" )
|
||||
continue;
|
||||
|
||||
INFO("Event class \"" << cn << "\"");
|
||||
|
||||
wxEvent* test;
|
||||
if ( ci->IsDynamic() )
|
||||
{
|
||||
test = wxDynamicCast(ci->CreateObject(),wxEvent);
|
||||
}
|
||||
else if ( cn == "wxTimerEvent" )
|
||||
{
|
||||
test = new wxTimerEvent(dummyTimer);
|
||||
}
|
||||
else
|
||||
{
|
||||
FAIL("Can't create objects of type " + cn);
|
||||
continue;
|
||||
}
|
||||
|
||||
REQUIRE( test );
|
||||
|
||||
wxEvent * const cloned = test->Clone();
|
||||
delete test;
|
||||
|
||||
REQUIRE( cloned );
|
||||
CHECK( cloned->GetClassInfo() == ci );
|
||||
|
||||
delete cloned;
|
||||
}
|
||||
}
|
||||
|
||||
156
libs/wxWidgets-3.3.1/tests/events/enterleave.cpp
Normal file
156
libs/wxWidgets-3.3.1/tests/events/enterleave.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: tests/events/enterleave.cpp
|
||||
// Purpose: Test wxEVT_ENTER_WINDOW and wxEVT_LEAVE_WINDOW events
|
||||
// Author: Ali Kettab
|
||||
// Created: 2024-10-16
|
||||
// Copyright: (c) 2024 wxWidgets team
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "testprec.h"
|
||||
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/app.h"
|
||||
#include "wx/button.h"
|
||||
#include "wx/panel.h"
|
||||
#include "wx/textctrl.h"
|
||||
#include "wx/window.h"
|
||||
#endif // WX_PRECOMP
|
||||
|
||||
#include "wx/uiaction.h"
|
||||
|
||||
#include "asserthelper.h"
|
||||
#include "testableframe.h"
|
||||
#include "waitfor.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// tests themselves
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#if wxUSE_UIACTIONSIMULATOR
|
||||
|
||||
TEST_CASE("EnterLeaveEvents", "[wxEvent][enter-leave]")
|
||||
{
|
||||
if ( !EnableUITests() )
|
||||
{
|
||||
WARN("Skipping wxEVT_{ENTER,LEAVE}_WINDOW tests: wxUIActionSimulator not available");
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<wxPanel>
|
||||
panel(new wxPanel(wxTheApp->GetTopWindow(), wxID_ANY));
|
||||
auto button = new wxButton(panel.get(), wxID_ANY, "button", {50, 50});
|
||||
auto textctrl = new wxTextCtrl(panel.get(), wxID_ANY, "", {160, 50});
|
||||
|
||||
EventCounter enter(panel.get(), wxEVT_ENTER_WINDOW);
|
||||
EventCounter leave(panel.get(), wxEVT_LEAVE_WINDOW);
|
||||
|
||||
// Wait for the first paint event to be sure that panel really
|
||||
// has its final size.
|
||||
WaitForPaint waitForPaint(panel.get());
|
||||
panel->SendSizeEventToParent();
|
||||
waitForPaint.YieldUntilPainted();
|
||||
|
||||
wxUIActionSimulator sim;
|
||||
|
||||
SECTION("Without mouse capture")
|
||||
{
|
||||
sim.MouseMove(panel->GetScreenPosition() + wxPoint(5, 5));
|
||||
wxYield();
|
||||
|
||||
CHECK( enter.GetCount() == 1 );
|
||||
CHECK( leave.GetCount() == 0 );
|
||||
|
||||
enter.Clear();
|
||||
|
||||
sim.MouseMove(button->GetScreenPosition() + wxPoint(5, 5));
|
||||
wxYield();
|
||||
|
||||
// The parent window (panel) should receive wxEVT_LEAVE_WINDOW event
|
||||
// when mouse enters the child window (button)
|
||||
CHECK( enter.GetCount() == 0 );
|
||||
CHECK( leave.GetCount() == 1 );
|
||||
|
||||
leave.Clear();
|
||||
|
||||
sim.MouseMove(panel->GetScreenPosition() + wxPoint(5, 5));
|
||||
wxYield();
|
||||
|
||||
// Now it (panel) should receive wxEVT_ENTER_WINDOW event when
|
||||
// the mouse leaves the button and enters the panel again.
|
||||
CHECK( enter.GetCount() == 1 );
|
||||
CHECK( leave.GetCount() == 0 );
|
||||
}
|
||||
|
||||
SECTION("With (implicit) mouse capture")
|
||||
{
|
||||
// Just to be sure that the button is really shown
|
||||
EventCounter clicked(button, wxEVT_BUTTON);
|
||||
|
||||
sim.MouseMove(button->GetScreenPosition() + wxPoint(5, 5));
|
||||
wxYield();
|
||||
|
||||
sim.MouseClick();
|
||||
wxYield();
|
||||
|
||||
CHECK( clicked.GetCount() == 1 );
|
||||
|
||||
enter.Clear();
|
||||
leave.Clear();
|
||||
|
||||
sim.MouseDown();
|
||||
wxYield();
|
||||
|
||||
#if defined(__WXGTK__) && !defined(__WXGTK3__)
|
||||
if ( IsAutomaticTest() )
|
||||
{
|
||||
WARN("Skipping tests known to fail under GitHub Actions");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
sim.MouseMove(button->GetScreenPosition() + wxPoint(10, 5));
|
||||
wxYield();
|
||||
|
||||
// Holding the mouse button down (initiated on the button) and then
|
||||
// hovering over the panel should not generate any events (enter/leave)
|
||||
// Additionally, entering and leaving another child (textctrl) while the
|
||||
// mouse is still held down should also not generate any events.
|
||||
|
||||
sim.MouseMove(panel->GetScreenPosition() + wxPoint(5, 5));
|
||||
wxYield();
|
||||
|
||||
CHECK( enter.GetCount() == 0 );
|
||||
CHECK( leave.GetCount() == 0 );
|
||||
|
||||
sim.MouseMove(textctrl->GetScreenPosition() + wxPoint(5, 5));
|
||||
wxYield();
|
||||
|
||||
CHECK( enter.GetCount() == 0 );
|
||||
CHECK( leave.GetCount() == 0 );
|
||||
|
||||
sim.MouseMove(panel->GetScreenPosition() + wxPoint(5, 5));
|
||||
wxYield();
|
||||
|
||||
CHECK( enter.GetCount() == 0 );
|
||||
CHECK( leave.GetCount() == 0 );
|
||||
|
||||
sim.MouseUp();
|
||||
wxYield();
|
||||
|
||||
// wxGTK behaves differently here, as it does not generate a
|
||||
// wxEVT_ENTER_WINDOW event when we release the mouse button.
|
||||
|
||||
#ifndef __WXGTK__
|
||||
CHECK( enter.GetCount() == 1 );
|
||||
#else
|
||||
CHECK( enter.GetCount() == 0 );
|
||||
#endif
|
||||
CHECK( leave.GetCount() == 0 );
|
||||
}
|
||||
}
|
||||
|
||||
#endif // wxUSE_UIACTIONSIMULATOR
|
||||
536
libs/wxWidgets-3.3.1/tests/events/evthandler.cpp
Normal file
536
libs/wxWidgets-3.3.1/tests/events/evthandler.cpp
Normal file
@@ -0,0 +1,536 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: tests/events/evthandler.cpp
|
||||
// Purpose: Test the new event types and wxEvtHandler-methods
|
||||
// Author: Peter Most
|
||||
// Created: 2009-01-24
|
||||
// Copyright: (c) 2009 Peter Most
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "testprec.h"
|
||||
|
||||
|
||||
#include "wx/event.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// test events and their handlers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
const wxEventType LegacyEventType = wxNewEventType();
|
||||
|
||||
class MyEvent;
|
||||
wxDEFINE_EVENT(MyEventType, MyEvent);
|
||||
|
||||
class MyEvent : public wxEvent
|
||||
{
|
||||
public:
|
||||
MyEvent() : wxEvent(0, MyEventType) { }
|
||||
|
||||
virtual wxEvent *Clone() const override { return new MyEvent; }
|
||||
};
|
||||
|
||||
typedef void (wxEvtHandler::*MyEventFunction)(MyEvent&);
|
||||
#define EVT_MYEVENT(func) \
|
||||
wx__DECLARE_EVT0(MyEventType, &func)
|
||||
|
||||
class AnotherEvent : public wxEvent
|
||||
{
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct Called
|
||||
{
|
||||
Called() { Reset(); }
|
||||
|
||||
void Reset()
|
||||
{
|
||||
function =
|
||||
functor =
|
||||
method =
|
||||
smethod = false;
|
||||
}
|
||||
|
||||
bool function,
|
||||
functor,
|
||||
method,
|
||||
smethod;
|
||||
} g_called;
|
||||
|
||||
void GlobalOnMyEvent(MyEvent&)
|
||||
{
|
||||
g_called.function = true;
|
||||
}
|
||||
|
||||
void GlobalOnEvent(wxEvent&)
|
||||
{
|
||||
g_called.function = true;
|
||||
}
|
||||
|
||||
#ifdef TEST_INVALID_BIND_GLOBAL
|
||||
void GlobalOnAnotherEvent(AnotherEvent&);
|
||||
#endif
|
||||
|
||||
void GlobalOnIdle(wxIdleEvent&)
|
||||
{
|
||||
g_called.function = true;
|
||||
}
|
||||
|
||||
struct MyFunctor
|
||||
{
|
||||
void operator()(MyEvent &) { g_called.functor = true; }
|
||||
};
|
||||
|
||||
struct IdleFunctor
|
||||
{
|
||||
void operator()(wxIdleEvent &) { g_called.functor = true; }
|
||||
};
|
||||
|
||||
class MyHandler : public wxEvtHandler
|
||||
{
|
||||
public:
|
||||
static void StaticOnMyEvent(MyEvent &) { g_called.smethod = true; }
|
||||
static void StaticOnAnotherEvent(AnotherEvent &);
|
||||
static void StaticOnIdle(wxIdleEvent&) { g_called.smethod = true; }
|
||||
|
||||
void OnMyEvent(MyEvent&) { g_called.method = true; }
|
||||
void OnEvent(wxEvent&) { g_called.method = true; }
|
||||
void OnAnotherEvent(AnotherEvent&);
|
||||
void OnIdle(wxIdleEvent&) { g_called.method = true; }
|
||||
|
||||
void OnOverloadedHandler(wxIdleEvent&) { }
|
||||
void OnOverloadedHandler(wxThreadEvent&) { }
|
||||
};
|
||||
|
||||
// we can also handle events in classes not deriving from wxEvtHandler
|
||||
struct MySink
|
||||
{
|
||||
void OnMyEvent(MyEvent&) { g_called.method = true; }
|
||||
void OnEvent(wxEvent&) { g_called.method = true; }
|
||||
void OnIdle(wxIdleEvent&) { g_called.method = true; }
|
||||
};
|
||||
|
||||
// also test event table compilation
|
||||
class MyClassWithEventTable : public wxEvtHandler
|
||||
{
|
||||
public:
|
||||
void OnMyEvent(MyEvent&) { g_called.method = true; }
|
||||
void OnEvent(wxEvent&) { g_called.method = true; }
|
||||
void OnAnotherEvent(AnotherEvent&);
|
||||
void OnIdle(wxIdleEvent&) { g_called.method = true; }
|
||||
#ifdef wxHAS_NOEXCEPT
|
||||
void OnIdleNoExcept(wxIdleEvent&) noexcept { }
|
||||
#endif
|
||||
|
||||
private:
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
// Avoid gcc warning about some of the functions defined by the expansion of
|
||||
// the event table macros being unused: they are indeed unused, but we still
|
||||
// want to have them to check that they compile.
|
||||
wxGCC_WARNING_SUPPRESS(unused-function)
|
||||
|
||||
wxBEGIN_EVENT_TABLE(MyClassWithEventTable, wxEvtHandler)
|
||||
EVT_IDLE(MyClassWithEventTable::OnIdle)
|
||||
|
||||
EVT_MYEVENT(MyClassWithEventTable::OnMyEvent)
|
||||
EVT_MYEVENT(MyClassWithEventTable::OnEvent)
|
||||
|
||||
#ifdef wxHAS_NOEXCEPT
|
||||
EVT_IDLE(MyClassWithEventTable::OnIdleNoExcept)
|
||||
#endif
|
||||
|
||||
// this shouldn't compile:
|
||||
//EVT_MYEVENT(MyClassWithEventTable::OnIdle)
|
||||
//EVT_IDLE(MyClassWithEventTable::OnAnotherEvent)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
wxGCC_WARNING_RESTORE(unused-function)
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
TEST_CASE("Event::BuiltinConnect", "[event][connect]")
|
||||
{
|
||||
MyHandler handler;
|
||||
|
||||
handler.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle));
|
||||
handler.Disconnect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle));
|
||||
|
||||
handler.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), nullptr, &handler);
|
||||
handler.Disconnect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), nullptr, &handler);
|
||||
|
||||
// using casts like this is even uglier than using wxIdleEventHandler and
|
||||
// results in warnings with gcc, but it should still continue to work for
|
||||
// compatibility
|
||||
wxGCC_WARNING_SUPPRESS_CAST_FUNCTION_TYPE()
|
||||
handler.Connect(wxEVT_IDLE, (wxObjectEventFunction)(wxEventFunction)&MyHandler::OnIdle);
|
||||
handler.Disconnect(wxEVT_IDLE, (wxObjectEventFunction)(wxEventFunction)&MyHandler::OnIdle);
|
||||
wxGCC_WARNING_RESTORE_CAST_FUNCTION_TYPE()
|
||||
|
||||
handler.Bind(wxEVT_IDLE, GlobalOnIdle);
|
||||
handler.Unbind(wxEVT_IDLE, GlobalOnIdle);
|
||||
|
||||
IdleFunctor f;
|
||||
handler.Bind(wxEVT_IDLE, f);
|
||||
handler.Unbind(wxEVT_IDLE, f);
|
||||
|
||||
handler.Bind(wxEVT_IDLE, &MyHandler::OnIdle, &handler);
|
||||
handler.Unbind(wxEVT_IDLE, &MyHandler::OnIdle, &handler);
|
||||
|
||||
handler.Bind(wxEVT_IDLE, &MyHandler::StaticOnIdle);
|
||||
handler.Unbind(wxEVT_IDLE, &MyHandler::StaticOnIdle);
|
||||
}
|
||||
|
||||
TEST_CASE("Event::LegacyConnect", "[event][connect]")
|
||||
{
|
||||
MyHandler handler;
|
||||
|
||||
handler.Connect( LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
|
||||
handler.Connect( 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
|
||||
handler.Connect( 0, 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
|
||||
|
||||
handler.Disconnect( LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
|
||||
handler.Disconnect( 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
|
||||
handler.Disconnect( 0, 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent );
|
||||
|
||||
|
||||
handler.Connect( LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, nullptr, &handler );
|
||||
handler.Connect( 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, nullptr, &handler );
|
||||
handler.Connect( 0, 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, nullptr, &handler );
|
||||
|
||||
handler.Disconnect( LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, nullptr, &handler );
|
||||
handler.Disconnect( 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, nullptr, &handler );
|
||||
handler.Disconnect( 0, 0, LegacyEventType, (wxObjectEventFunction)&MyHandler::OnEvent, nullptr, &handler );
|
||||
}
|
||||
|
||||
TEST_CASE("Event::ConnectOverloaded", "[event][connect]")
|
||||
{
|
||||
MyHandler handler;
|
||||
|
||||
handler.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnOverloadedHandler));
|
||||
handler.Connect(wxEVT_THREAD, wxThreadEventHandler(MyHandler::OnOverloadedHandler));
|
||||
}
|
||||
|
||||
TEST_CASE("Event::DisconnectWildcard", "[event][connect][disconnect]")
|
||||
{
|
||||
MyHandler handler;
|
||||
|
||||
// should be able to disconnect a different handler using "wildcard search"
|
||||
MyHandler sink;
|
||||
wxEvtHandler source;
|
||||
source.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), nullptr, &sink);
|
||||
CHECK(source.Disconnect(wxID_ANY, wxEVT_IDLE));
|
||||
// destruction of source and sink here should properly clean up the
|
||||
// wxEventConnectionRef without crashing
|
||||
}
|
||||
|
||||
TEST_CASE("Event::AutoDisconnect", "[event][connect][disconnect]")
|
||||
{
|
||||
wxEvtHandler source;
|
||||
{
|
||||
MyHandler sink;
|
||||
source.Connect(wxEVT_IDLE, wxIdleEventHandler(MyHandler::OnIdle), nullptr, &sink);
|
||||
// mismatched event type, so nothing should be disconnected
|
||||
CHECK(!source.Disconnect(wxEVT_THREAD, wxIdleEventHandler(MyHandler::OnIdle), nullptr, &sink));
|
||||
}
|
||||
// destruction of sink should have automatically disconnected it, so
|
||||
// there should be nothing to disconnect anymore
|
||||
CHECK(!source.Disconnect(wxID_ANY, wxEVT_IDLE));
|
||||
}
|
||||
|
||||
TEST_CASE("Event::BindFunction", "[event][bind]")
|
||||
{
|
||||
MyHandler handler;
|
||||
MyEvent e;
|
||||
|
||||
// function tests
|
||||
handler.Bind( MyEventType, GlobalOnMyEvent );
|
||||
g_called.Reset();
|
||||
handler.ProcessEvent(e);
|
||||
CHECK( g_called.function );
|
||||
handler.Unbind( MyEventType, GlobalOnMyEvent );
|
||||
g_called.Reset();
|
||||
handler.ProcessEvent(e);
|
||||
CHECK( !g_called.function ); // check that it was disconnected
|
||||
|
||||
handler.Bind( MyEventType, GlobalOnMyEvent, 0 );
|
||||
handler.Unbind( MyEventType, GlobalOnMyEvent, 0 );
|
||||
|
||||
handler.Bind( MyEventType, GlobalOnMyEvent, 0, 0 );
|
||||
handler.Unbind( MyEventType, GlobalOnMyEvent, 0, 0 );
|
||||
}
|
||||
|
||||
TEST_CASE("Event::BindStaticMethod", "[event][bind]")
|
||||
{
|
||||
MyHandler handler;
|
||||
MyEvent e;
|
||||
|
||||
// static method tests (this is same as functions but still test it just in
|
||||
// case we hit some strange compiler bugs)
|
||||
handler.Bind( MyEventType, &MyHandler::StaticOnMyEvent );
|
||||
g_called.Reset();
|
||||
handler.ProcessEvent(e);
|
||||
CHECK( g_called.smethod );
|
||||
handler.Unbind( MyEventType, &MyHandler::StaticOnMyEvent );
|
||||
g_called.Reset();
|
||||
handler.ProcessEvent(e);
|
||||
CHECK( !g_called.smethod );
|
||||
|
||||
handler.Bind( MyEventType, &MyHandler::StaticOnMyEvent, 0 );
|
||||
handler.Unbind( MyEventType, &MyHandler::StaticOnMyEvent, 0 );
|
||||
|
||||
handler.Bind( MyEventType, &MyHandler::StaticOnMyEvent, 0, 0 );
|
||||
handler.Unbind( MyEventType, &MyHandler::StaticOnMyEvent, 0, 0 );
|
||||
}
|
||||
|
||||
TEST_CASE("Event::BindFunctor", "[event][bind]")
|
||||
{
|
||||
MyHandler handler;
|
||||
MyEvent e;
|
||||
|
||||
// generalized functor tests
|
||||
MyFunctor functor;
|
||||
|
||||
handler.Bind( MyEventType, functor );
|
||||
g_called.Reset();
|
||||
handler.ProcessEvent(e);
|
||||
CHECK( g_called.functor );
|
||||
handler.Unbind( MyEventType, functor );
|
||||
g_called.Reset();
|
||||
handler.ProcessEvent(e);
|
||||
CHECK( !g_called.functor );
|
||||
|
||||
handler.Bind( MyEventType, functor, 0 );
|
||||
handler.Unbind( MyEventType, functor, 0 );
|
||||
|
||||
handler.Bind( MyEventType, functor, 0, 0 );
|
||||
handler.Unbind( MyEventType, functor, 0, 0 );
|
||||
|
||||
// test that a temporary functor is working as well and also test that
|
||||
// unbinding a different (though equal) instance of the same functor does
|
||||
// not work
|
||||
MyFunctor func;
|
||||
handler.Bind( MyEventType, MyFunctor() );
|
||||
CHECK( !handler.Unbind( MyEventType, func ));
|
||||
|
||||
handler.Bind( MyEventType, MyFunctor(), 0 );
|
||||
CHECK( !handler.Unbind( MyEventType, func, 0 ));
|
||||
|
||||
handler.Bind( MyEventType, MyFunctor(), 0, 0 );
|
||||
CHECK( !handler.Unbind( MyEventType, func, 0, 0 ));
|
||||
}
|
||||
|
||||
TEST_CASE("Event::BindMethod", "[event][bind]")
|
||||
{
|
||||
MyHandler handler;
|
||||
MyEvent e;
|
||||
|
||||
// class method tests
|
||||
handler.Bind( MyEventType, &MyHandler::OnMyEvent, &handler );
|
||||
g_called.Reset();
|
||||
handler.ProcessEvent(e);
|
||||
CHECK( g_called.method );
|
||||
handler.Unbind( MyEventType, &MyHandler::OnMyEvent, &handler );
|
||||
g_called.Reset();
|
||||
handler.ProcessEvent(e);
|
||||
CHECK( !g_called.method );
|
||||
|
||||
handler.Bind( MyEventType, &MyHandler::OnMyEvent, &handler, 0 );
|
||||
handler.Unbind( MyEventType, &MyHandler::OnMyEvent, &handler, 0 );
|
||||
|
||||
handler.Bind( MyEventType, &MyHandler::OnMyEvent, &handler, 0, 0 );
|
||||
handler.Unbind( MyEventType, &MyHandler::OnMyEvent, &handler, 0, 0 );
|
||||
}
|
||||
|
||||
TEST_CASE("Event::BindMethodUsingBaseEvent", "[event][bind]")
|
||||
{
|
||||
MyHandler handler;
|
||||
MyEvent e;
|
||||
|
||||
// test connecting a method taking just wxEvent and not MyEvent: this
|
||||
// should work too if we don't need any MyEvent-specific information in the
|
||||
// handler
|
||||
handler.Bind( MyEventType, &MyHandler::OnEvent, &handler );
|
||||
g_called.Reset();
|
||||
handler.ProcessEvent(e);
|
||||
CHECK( g_called.method );
|
||||
handler.Unbind( MyEventType, &MyHandler::OnEvent, &handler );
|
||||
g_called.Reset();
|
||||
handler.ProcessEvent(e);
|
||||
CHECK( !g_called.method );
|
||||
|
||||
handler.Bind( MyEventType, &MyHandler::OnEvent, &handler, 0 );
|
||||
handler.Unbind( MyEventType, &MyHandler::OnEvent, &handler, 0 );
|
||||
|
||||
handler.Bind( MyEventType, &MyHandler::OnEvent, &handler, 0, 0 );
|
||||
handler.Unbind( MyEventType, &MyHandler::OnEvent, &handler, 0, 0 );
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("Event::BindFunctionUsingBaseEvent", "[event][bind]")
|
||||
{
|
||||
MyHandler handler;
|
||||
MyEvent e;
|
||||
|
||||
// test connecting a function taking just wxEvent and not MyEvent: this
|
||||
// should work too if we don't need any MyEvent-specific information in the
|
||||
// handler
|
||||
handler.Bind( MyEventType, GlobalOnEvent );
|
||||
g_called.Reset();
|
||||
handler.ProcessEvent(e);
|
||||
CHECK( g_called.function );
|
||||
handler.Unbind( MyEventType, GlobalOnEvent );
|
||||
g_called.Reset();
|
||||
handler.ProcessEvent(e);
|
||||
CHECK( !g_called.function );
|
||||
|
||||
handler.Bind( MyEventType, GlobalOnEvent, 0 );
|
||||
handler.Unbind( MyEventType, GlobalOnEvent, 0 );
|
||||
|
||||
handler.Bind( MyEventType, GlobalOnEvent, 0, 0 );
|
||||
handler.Unbind( MyEventType, GlobalOnEvent, 0, 0 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
TEST_CASE("Event::BindNonHandler", "[event][bind]")
|
||||
{
|
||||
MyHandler handler;
|
||||
MyEvent e;
|
||||
|
||||
// class method tests for class not derived from wxEvtHandler
|
||||
MySink sink;
|
||||
|
||||
handler.Bind( MyEventType, &MySink::OnMyEvent, &sink );
|
||||
g_called.Reset();
|
||||
handler.ProcessEvent(e);
|
||||
CHECK( g_called.method );
|
||||
handler.Unbind( MyEventType, &MySink::OnMyEvent, &sink );
|
||||
g_called.Reset();
|
||||
handler.ProcessEvent(e);
|
||||
CHECK( !g_called.method );
|
||||
}
|
||||
|
||||
TEST_CASE("Event::InvalidBind", "[event][bind]")
|
||||
{
|
||||
// these calls shouldn't compile but we unfortunately can't check this
|
||||
// automatically, you need to uncomment them manually and test that
|
||||
// compilation does indeed fail
|
||||
|
||||
// connecting a handler with incompatible signature shouldn't work
|
||||
#ifdef TEST_INVALID_BIND_GLOBAL
|
||||
handler.Bind(MyEventType, GlobalOnAnotherEvent);
|
||||
#endif
|
||||
#ifdef TEST_INVALID_BIND_STATIC
|
||||
handler.Bind(MyEventType, &MyHandler::StaticOnAnotherEvent);
|
||||
#endif
|
||||
#ifdef TEST_INVALID_BIND_METHOD
|
||||
handler.Bind(MyEventType, &MyHandler::OnAnotherEvent, &handler);
|
||||
#endif
|
||||
#ifdef TEST_INVALID_BIND_FUNCTOR
|
||||
IdleFunctor f;
|
||||
handler.Bind(MyEventType, f);
|
||||
#endif
|
||||
|
||||
// the handler can't be omitted when calling Bind()
|
||||
#ifdef TEST_INVALID_BIND_NO_HANDLER
|
||||
handler.Bind(MyEventType, &MyHandler::OnMyEvent);
|
||||
#endif
|
||||
|
||||
// calling a derived class method with a base class pointer must not work
|
||||
#ifdef TEST_INVALID_BIND_DERIVED
|
||||
struct C1 : wxEvtHandler { };
|
||||
struct C2 : wxEvtHandler { void OnWhatever(wxEvent&); };
|
||||
C1 c1;
|
||||
c1.Bind(&C2::OnWhatever);
|
||||
#endif
|
||||
|
||||
// using object pointer incompatible with the method must not work
|
||||
#ifdef TEST_INVALID_BIND_WRONG_CLASS
|
||||
MySink mySink;
|
||||
MyHandler myHandler;
|
||||
myHandler.Bind(MyEventType, &MyHandler::OnMyEvent, &mySink);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Helpers for UnbindFromHandler() test, have to be declared outside of the
|
||||
// function in C++98.
|
||||
struct Handler1
|
||||
{
|
||||
void OnDontCall(MyEvent&)
|
||||
{
|
||||
// Although this handler is bound, the second one below is bound
|
||||
// later and so will be called first and will disconnect this one
|
||||
// before it has a chance to be called.
|
||||
FAIL("shouldn't be called");
|
||||
}
|
||||
};
|
||||
|
||||
class Handler2
|
||||
{
|
||||
public:
|
||||
Handler2(MyHandler& handler, Handler1& h1)
|
||||
: m_handler(handler),
|
||||
m_h1(h1)
|
||||
{
|
||||
}
|
||||
|
||||
void OnUnbind(MyEvent& e)
|
||||
{
|
||||
m_handler.Unbind(MyEventType, &Handler1::OnDontCall, &m_h1);
|
||||
|
||||
// Check that the now disconnected first handler is not executed.
|
||||
e.Skip();
|
||||
}
|
||||
|
||||
private:
|
||||
MyHandler& m_handler;
|
||||
Handler1& m_h1;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(Handler2);
|
||||
};
|
||||
|
||||
TEST_CASE("Event::UnbindFromHandler", "[event][bind][unbind]")
|
||||
{
|
||||
MyHandler handler;
|
||||
MyEvent e;
|
||||
|
||||
Handler1 h1;
|
||||
handler.Bind(MyEventType, &Handler1::OnDontCall, &h1);
|
||||
|
||||
Handler2 h2(handler, h1);
|
||||
handler.Bind(MyEventType, &Handler2::OnUnbind, &h2);
|
||||
|
||||
handler.ProcessEvent(e);
|
||||
}
|
||||
|
||||
// This is a compilation-time-only test: just check that a class inheriting
|
||||
// from wxEvtHandler non-publicly can use Bind() with its method, this used to
|
||||
// result in compilation errors.
|
||||
class HandlerNonPublic : protected wxEvtHandler
|
||||
{
|
||||
public:
|
||||
HandlerNonPublic()
|
||||
{
|
||||
Bind(wxEVT_IDLE, &HandlerNonPublic::OnIdle, this);
|
||||
}
|
||||
|
||||
void OnIdle(wxIdleEvent&) { }
|
||||
};
|
||||
|
||||
// Another compilation-time-only test, but this one checking that these event
|
||||
// objects can't be created from outside of the library.
|
||||
#ifdef TEST_INVALID_EVENT_CREATION
|
||||
|
||||
void TestEventCreation()
|
||||
{
|
||||
wxPaintEvent eventPaint;
|
||||
}
|
||||
|
||||
#endif // TEST_INVALID_EVENT_CREATION
|
||||
124
libs/wxWidgets-3.3.1/tests/events/evtlooptest.cpp
Normal file
124
libs/wxWidgets-3.3.1/tests/events/evtlooptest.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: tests/events/evtloop.cpp
|
||||
// Purpose: Tests for the event loop classes
|
||||
// Author: Rob Bresalier
|
||||
// Created: 2013-05-02
|
||||
// Copyright: (c) 2013 Rob Bresalier
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "testprec.h"
|
||||
|
||||
|
||||
#include "wx/timer.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// constants
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Use two arbitrary but different return codes for the two loops.
|
||||
const int EXIT_CODE_OUTER_LOOP = 99;
|
||||
const int EXIT_CODE_INNER_LOOP = 55;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// test class
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class EvtloopTestCase : public CppUnit::TestCase
|
||||
{
|
||||
public:
|
||||
EvtloopTestCase() { }
|
||||
|
||||
private:
|
||||
CPPUNIT_TEST_SUITE( EvtloopTestCase );
|
||||
CPPUNIT_TEST( TestExit );
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
void TestExit();
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(EvtloopTestCase);
|
||||
};
|
||||
|
||||
// register in the unnamed registry so that these tests are run by default
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION( EvtloopTestCase );
|
||||
|
||||
// also include in its own registry so that these tests can be run alone
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( EvtloopTestCase, "EvtloopTestCase" );
|
||||
|
||||
|
||||
// Helper class to schedule exit of the given event loop after the specified
|
||||
// delay.
|
||||
class ScheduleLoopExitTimer : public wxTimer
|
||||
{
|
||||
public:
|
||||
ScheduleLoopExitTimer(wxEventLoop& loop, int rc)
|
||||
: m_loop(loop),
|
||||
m_rc(rc)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Notify() override
|
||||
{
|
||||
m_loop.ScheduleExit(m_rc);
|
||||
}
|
||||
|
||||
private:
|
||||
wxEventLoop& m_loop;
|
||||
const int m_rc;
|
||||
};
|
||||
|
||||
// Another helper which runs a nested loop and schedules exiting both the outer
|
||||
// and the inner loop after the specified delays.
|
||||
class RunNestedAndExitBothLoopsTimer : public wxTimer
|
||||
{
|
||||
public:
|
||||
RunNestedAndExitBothLoopsTimer(wxTimer& timerOuter,
|
||||
int loopOuterDuration,
|
||||
int loopInnerDuration)
|
||||
: m_timerOuter(timerOuter),
|
||||
m_loopOuterDuration(loopOuterDuration),
|
||||
m_loopInnerDuration(loopInnerDuration)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Notify() override
|
||||
{
|
||||
wxEventLoop loopInner;
|
||||
ScheduleLoopExitTimer timerInner(loopInner, EXIT_CODE_INNER_LOOP);
|
||||
|
||||
m_timerOuter.StartOnce(m_loopOuterDuration);
|
||||
timerInner.StartOnce(m_loopInnerDuration);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL( EXIT_CODE_INNER_LOOP, loopInner.Run() );
|
||||
}
|
||||
|
||||
private:
|
||||
wxTimer& m_timerOuter;
|
||||
const int m_loopOuterDuration;
|
||||
const int m_loopInnerDuration;
|
||||
};
|
||||
|
||||
void EvtloopTestCase::TestExit()
|
||||
{
|
||||
// Test that simply exiting the loop works.
|
||||
wxEventLoop loopOuter;
|
||||
ScheduleLoopExitTimer timerExit(loopOuter, EXIT_CODE_OUTER_LOOP);
|
||||
timerExit.StartOnce(1);
|
||||
CPPUNIT_ASSERT_EQUAL( EXIT_CODE_OUTER_LOOP, loopOuter.Run() );
|
||||
|
||||
// Test that exiting the outer loop before the inner loop (outer duration
|
||||
// parameter less than inner duration in the timer ctor below) works.
|
||||
ScheduleLoopExitTimer timerExitOuter(loopOuter, EXIT_CODE_OUTER_LOOP);
|
||||
RunNestedAndExitBothLoopsTimer timerRun(timerExitOuter, 5, 10);
|
||||
timerRun.StartOnce(1);
|
||||
CPPUNIT_ASSERT_EQUAL( EXIT_CODE_OUTER_LOOP, loopOuter.Run() );
|
||||
|
||||
// Test that exiting the inner loop before the outer one works too.
|
||||
ScheduleLoopExitTimer timerExitOuter2(loopOuter, EXIT_CODE_OUTER_LOOP);
|
||||
RunNestedAndExitBothLoopsTimer timerRun2(timerExitOuter, 10, 5);
|
||||
timerRun2.StartOnce(1);
|
||||
CPPUNIT_ASSERT_EQUAL( EXIT_CODE_OUTER_LOOP, loopOuter.Run() );
|
||||
}
|
||||
14
libs/wxWidgets-3.3.1/tests/events/evtsource.cpp
Normal file
14
libs/wxWidgets-3.3.1/tests/events/evtsource.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: tests/events/evtsource.cpp
|
||||
// Purpose: Test the event sources
|
||||
// Author: Bartosz Bekier
|
||||
// Created: 2009-01-24
|
||||
// Copyright: (c) 2009 Bartosz Bekier <bartosz.bekier@gmail.com>
|
||||
// Licence: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "testprec.h"
|
||||
376
libs/wxWidgets-3.3.1/tests/events/keyboard.cpp
Normal file
376
libs/wxWidgets-3.3.1/tests/events/keyboard.cpp
Normal file
@@ -0,0 +1,376 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// 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"
|
||||
|
||||
#include "waitfor.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 ( 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() );
|
||||
}
|
||||
|
||||
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() override;
|
||||
virtual void tearDown() override;
|
||||
|
||||
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();
|
||||
|
||||
YieldForAWhile(10); // 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()
|
||||
{
|
||||
#ifdef __WXQT__
|
||||
WARN("FIXME! doesn't work like the other ports.");
|
||||
#else
|
||||
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' );
|
||||
#endif
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
#ifdef __WXQT__
|
||||
WARN("FIXME! doesn't work like the other ports.");
|
||||
#else
|
||||
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) );
|
||||
#endif
|
||||
}
|
||||
|
||||
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
|
||||
832
libs/wxWidgets-3.3.1/tests/events/propagation.cpp
Normal file
832
libs/wxWidgets-3.3.1/tests/events/propagation.cpp
Normal file
@@ -0,0 +1,832 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: tests/events/propagation.cpp
|
||||
// Purpose: Test events propagation
|
||||
// Author: Vadim Zeitlin
|
||||
// Created: 2009-01-16
|
||||
// Copyright: (c) 2009 Vadim Zeitlin <vadim@wxwidgets.org>
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "testprec.h"
|
||||
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/app.h"
|
||||
#include "wx/event.h"
|
||||
#include "wx/scrolwin.h"
|
||||
#include "wx/window.h"
|
||||
#endif // WX_PRECOMP
|
||||
|
||||
#include "wx/docmdi.h"
|
||||
#include "wx/frame.h"
|
||||
#include "wx/menu.h"
|
||||
#include "wx/scopeguard.h"
|
||||
#include "wx/toolbar.h"
|
||||
#include "wx/uiaction.h"
|
||||
#if wxUSE_AUI
|
||||
#include "wx/aui/framemanager.h"
|
||||
#include "wx/aui/tabmdi.h"
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "waitfor.h"
|
||||
|
||||
// FIXME: Currently under OS X testing paint event doesn't work because neither
|
||||
// calling Refresh()+Update() nor even sending wxPaintEvent directly to
|
||||
// the window doesn't result in calls to its event handlers, so disable
|
||||
// some tests there. But this should be fixed and the tests reenabled
|
||||
// because wxPaintEvent propagation in wxScrolledWindow is a perfect
|
||||
// example of fragile code that could be broken under OS X.
|
||||
#if !defined(__WXOSX__)
|
||||
#define CAN_TEST_PAINT_EVENTS
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// this string will record the execution of all handlers
|
||||
wxString g_str;
|
||||
|
||||
// a custom event
|
||||
wxDEFINE_EVENT(TEST_EVT, wxCommandEvent);
|
||||
|
||||
// a custom event handler tracing the propagation of the events of the
|
||||
// specified types
|
||||
template <class Event>
|
||||
class TestEvtHandlerBase : public wxEvtHandler
|
||||
{
|
||||
public:
|
||||
TestEvtHandlerBase(wxEventType evtType, char tag)
|
||||
: m_evtType(evtType),
|
||||
m_tag(tag)
|
||||
{
|
||||
Connect(evtType,
|
||||
static_cast<wxEventFunction>(&TestEvtHandlerBase::OnTest));
|
||||
}
|
||||
|
||||
// override ProcessEvent() to confirm that it is called for all event
|
||||
// handlers in the chain
|
||||
virtual bool ProcessEvent(wxEvent& event) override
|
||||
{
|
||||
if ( event.GetEventType() == m_evtType )
|
||||
g_str += 'o'; // "o" == "overridden"
|
||||
|
||||
return wxEvtHandler::ProcessEvent(event);
|
||||
}
|
||||
|
||||
private:
|
||||
void OnTest(wxEvent& event)
|
||||
{
|
||||
g_str += m_tag;
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
const wxEventType m_evtType;
|
||||
const char m_tag;
|
||||
|
||||
wxDECLARE_NO_COPY_TEMPLATE_CLASS(TestEvtHandlerBase, Event);
|
||||
};
|
||||
|
||||
struct TestEvtHandler : TestEvtHandlerBase<wxCommandEvent>
|
||||
{
|
||||
TestEvtHandler(char tag)
|
||||
: TestEvtHandlerBase<wxCommandEvent>(TEST_EVT, tag)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct TestMenuEvtHandler : TestEvtHandlerBase<wxCommandEvent>
|
||||
{
|
||||
TestMenuEvtHandler(char tag)
|
||||
: TestEvtHandlerBase<wxCommandEvent>(wxEVT_MENU, tag)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct TestPaintEvtHandler : TestEvtHandlerBase<wxPaintEvent>
|
||||
{
|
||||
TestPaintEvtHandler(char tag)
|
||||
: TestEvtHandlerBase<wxPaintEvent>(wxEVT_PAINT, tag)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// Another custom event handler, suitable for use with Connect().
|
||||
struct TestEvtSink : wxEvtHandler
|
||||
{
|
||||
TestEvtSink(char tag)
|
||||
: m_tag(tag)
|
||||
{
|
||||
}
|
||||
|
||||
void Handle(wxEvent& event)
|
||||
{
|
||||
g_str += m_tag;
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
const char m_tag;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(TestEvtSink);
|
||||
};
|
||||
|
||||
// a window handling the test event
|
||||
class TestWindow : public wxWindow
|
||||
{
|
||||
public:
|
||||
TestWindow(wxWindow *parent, char tag)
|
||||
: wxWindow(parent, wxID_ANY),
|
||||
m_tag(tag)
|
||||
{
|
||||
Connect(TEST_EVT, wxCommandEventHandler(TestWindow::OnTest));
|
||||
}
|
||||
|
||||
private:
|
||||
void OnTest(wxCommandEvent& event)
|
||||
{
|
||||
g_str += m_tag;
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
const char m_tag;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(TestWindow);
|
||||
};
|
||||
|
||||
// a scroll window handling paint event: we want to have a special test case
|
||||
// for this because the event propagation is complicated even further than
|
||||
// usual here by the presence of wxScrollHelperEvtHandler in the event handlers
|
||||
// chain and the fact that OnDraw() virtual method must be called if EVT_PAINT
|
||||
// is not handled
|
||||
class TestScrollWindow : public wxScrolledWindow
|
||||
{
|
||||
public:
|
||||
TestScrollWindow(wxWindow *parent)
|
||||
: wxScrolledWindow(parent, wxID_ANY)
|
||||
{
|
||||
Connect(wxEVT_PAINT, wxPaintEventHandler(TestScrollWindow::OnPaint));
|
||||
}
|
||||
|
||||
void GeneratePaintEvent()
|
||||
{
|
||||
#if defined(__WXGTK__) || defined(__WXQT__)
|
||||
// We need to map the window, otherwise we're not going to get any
|
||||
// paint events for it.
|
||||
YieldForAWhile();
|
||||
|
||||
// Ignore events generated during the initial mapping.
|
||||
g_str.clear();
|
||||
#endif // __WXGTK__ || __WXQT__
|
||||
|
||||
Refresh();
|
||||
Update();
|
||||
}
|
||||
|
||||
virtual void OnDraw(wxDC& WXUNUSED(dc)) override
|
||||
{
|
||||
g_str += 'D'; // draw
|
||||
}
|
||||
|
||||
private:
|
||||
void OnPaint(wxPaintEvent& event)
|
||||
{
|
||||
g_str += 'P'; // paint
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(TestScrollWindow);
|
||||
};
|
||||
|
||||
int DoFilterEvent(wxEvent& event)
|
||||
{
|
||||
if ( event.GetEventType() == TEST_EVT ||
|
||||
event.GetEventType() == wxEVT_MENU )
|
||||
g_str += 'a';
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool DoProcessEvent(wxEvent& event)
|
||||
{
|
||||
if ( event.GetEventType() == TEST_EVT ||
|
||||
event.GetEventType() == wxEVT_MENU )
|
||||
g_str += 'A';
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// test class
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
class EventPropagationTestCase : public CppUnit::TestCase
|
||||
{
|
||||
public:
|
||||
EventPropagationTestCase() {}
|
||||
|
||||
virtual void setUp() override;
|
||||
virtual void tearDown() override;
|
||||
|
||||
private:
|
||||
CPPUNIT_TEST_SUITE( EventPropagationTestCase );
|
||||
CPPUNIT_TEST( OneHandler );
|
||||
CPPUNIT_TEST( TwoHandlers );
|
||||
CPPUNIT_TEST( WindowWithoutHandler );
|
||||
CPPUNIT_TEST( WindowWithHandler );
|
||||
CPPUNIT_TEST( ForwardEvent );
|
||||
CPPUNIT_TEST( ScrollWindowWithoutHandler );
|
||||
CPPUNIT_TEST( ScrollWindowWithHandler );
|
||||
// for unknown reason, this test will cause the tests segmentation failed
|
||||
// under x11, disable it for now.
|
||||
#if !defined (__WXX11__) && wxUSE_MENUS
|
||||
CPPUNIT_TEST( MenuEvent );
|
||||
#endif
|
||||
#if wxUSE_DOC_VIEW_ARCHITECTURE
|
||||
CPPUNIT_TEST( DocView );
|
||||
#if wxUSE_AUI
|
||||
CPPUNIT_TEST( DocViewAui );
|
||||
#endif
|
||||
#endif // wxUSE_DOC_VIEW_ARCHITECTURE
|
||||
WXUISIM_TEST( ContextMenuEvent );
|
||||
WXUISIM_TEST( PropagationLevel );
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
void OneHandler();
|
||||
void TwoHandlers();
|
||||
void WindowWithoutHandler();
|
||||
void WindowWithHandler();
|
||||
void ForwardEvent();
|
||||
void ScrollWindowWithoutHandler();
|
||||
void ScrollWindowWithHandler();
|
||||
#if wxUSE_MENUS
|
||||
void MenuEvent();
|
||||
#endif
|
||||
#if wxUSE_DOC_VIEW_ARCHITECTURE
|
||||
void DocView();
|
||||
#if wxUSE_AUI
|
||||
void DocViewAui();
|
||||
#endif
|
||||
void DocViewCommon(wxFrame* (*newParent)(wxDocManager *manager,
|
||||
wxFrame *parent,
|
||||
wxWindowID id,
|
||||
const wxString& title),
|
||||
wxFrame* (*newChild)(wxDocument *doc,
|
||||
wxView *view,
|
||||
wxFrame *parent,
|
||||
wxWindowID id,
|
||||
const wxString& title));
|
||||
#endif // wxUSE_DOC_VIEW_ARCHITECTURE
|
||||
#if wxUSE_UIACTIONSIMULATOR
|
||||
void ContextMenuEvent();
|
||||
void PropagationLevel();
|
||||
#endif
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(EventPropagationTestCase);
|
||||
};
|
||||
|
||||
// register in the unnamed registry so that these tests are run by default
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION( EventPropagationTestCase );
|
||||
|
||||
// also include in its own registry so that these tests can be run alone
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( EventPropagationTestCase, "EventPropagationTestCase" );
|
||||
|
||||
void EventPropagationTestCase::setUp()
|
||||
{
|
||||
SetFilterEventFunc(DoFilterEvent);
|
||||
SetProcessEventFunc(DoProcessEvent);
|
||||
|
||||
g_str.clear();
|
||||
}
|
||||
|
||||
void EventPropagationTestCase::tearDown()
|
||||
{
|
||||
SetFilterEventFunc(nullptr);
|
||||
SetProcessEventFunc(nullptr);
|
||||
}
|
||||
|
||||
void EventPropagationTestCase::OneHandler()
|
||||
{
|
||||
wxCommandEvent event(TEST_EVT);
|
||||
TestEvtHandler h1('1');
|
||||
h1.ProcessEvent(event);
|
||||
CPPUNIT_ASSERT_EQUAL( "oa1A", g_str );
|
||||
}
|
||||
|
||||
void EventPropagationTestCase::TwoHandlers()
|
||||
{
|
||||
wxCommandEvent event(TEST_EVT);
|
||||
TestEvtHandler h1('1');
|
||||
TestEvtHandler h2('2');
|
||||
h1.SetNextHandler(&h2);
|
||||
h2.SetPreviousHandler(&h1);
|
||||
h1.ProcessEvent(event);
|
||||
CPPUNIT_ASSERT_EQUAL( "oa1o2A", g_str );
|
||||
}
|
||||
|
||||
void EventPropagationTestCase::WindowWithoutHandler()
|
||||
{
|
||||
wxCommandEvent event(TEST_EVT);
|
||||
TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
|
||||
wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
|
||||
|
||||
TestWindow * const child = new TestWindow(parent, 'c');
|
||||
|
||||
child->GetEventHandler()->ProcessEvent(event);
|
||||
CPPUNIT_ASSERT_EQUAL( "acpA", g_str );
|
||||
}
|
||||
|
||||
void EventPropagationTestCase::WindowWithHandler()
|
||||
{
|
||||
wxCommandEvent event(TEST_EVT);
|
||||
TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
|
||||
wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
|
||||
|
||||
TestWindow * const child = new TestWindow(parent, 'c');
|
||||
|
||||
TestEvtHandler h1('1');
|
||||
child->PushEventHandler(&h1);
|
||||
wxON_BLOCK_EXIT_OBJ1( *child, wxWindow::PopEventHandler, false );
|
||||
TestEvtHandler h2('2');
|
||||
child->PushEventHandler(&h2);
|
||||
wxON_BLOCK_EXIT_OBJ1( *child, wxWindow::PopEventHandler, false );
|
||||
|
||||
child->HandleWindowEvent(event);
|
||||
CPPUNIT_ASSERT_EQUAL( "oa2o1cpA", g_str );
|
||||
}
|
||||
|
||||
void EventPropagationTestCase::ForwardEvent()
|
||||
{
|
||||
// The idea of this test is to check that the events explicitly forwarded
|
||||
// to another event handler still get pre/post-processed as usual as this
|
||||
// used to be broken by the fixes trying to avoid duplicate processing.
|
||||
TestWindow * const win = new TestWindow(wxTheApp->GetTopWindow(), 'w');
|
||||
wxON_BLOCK_EXIT_OBJ0( *win, wxWindow::Destroy );
|
||||
|
||||
TestEvtHandler h1('1');
|
||||
win->PushEventHandler(&h1);
|
||||
wxON_BLOCK_EXIT_OBJ1( *win, wxWindow::PopEventHandler, false );
|
||||
|
||||
class ForwardEvtHandler : public wxEvtHandler
|
||||
{
|
||||
public:
|
||||
ForwardEvtHandler(wxEvtHandler& h) : m_h(&h) { }
|
||||
|
||||
virtual bool ProcessEvent(wxEvent& event) override
|
||||
{
|
||||
g_str += 'f';
|
||||
|
||||
return m_h->ProcessEvent(event);
|
||||
}
|
||||
|
||||
private:
|
||||
wxEvtHandler *m_h;
|
||||
} f(h1);
|
||||
|
||||
// First send the event directly to f.
|
||||
wxCommandEvent event1(TEST_EVT);
|
||||
f.ProcessEvent(event1);
|
||||
CPPUNIT_ASSERT_EQUAL( "foa1wA", g_str );
|
||||
g_str.clear();
|
||||
|
||||
// And then also test sending it to f indirectly.
|
||||
wxCommandEvent event2(TEST_EVT);
|
||||
TestEvtHandler h2('2');
|
||||
h2.SetNextHandler(&f);
|
||||
h2.ProcessEvent(event2);
|
||||
CPPUNIT_ASSERT_EQUAL( "oa2fo1wAA", g_str );
|
||||
}
|
||||
|
||||
void EventPropagationTestCase::ScrollWindowWithoutHandler()
|
||||
{
|
||||
TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
|
||||
wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
|
||||
|
||||
TestScrollWindow * const win = new TestScrollWindow(parent);
|
||||
|
||||
#ifdef CAN_TEST_PAINT_EVENTS
|
||||
win->GeneratePaintEvent();
|
||||
CPPUNIT_ASSERT_EQUAL( "PD", g_str );
|
||||
#endif
|
||||
|
||||
g_str.clear();
|
||||
wxCommandEvent eventCmd(TEST_EVT);
|
||||
win->HandleWindowEvent(eventCmd);
|
||||
CPPUNIT_ASSERT_EQUAL( "apA", g_str );
|
||||
}
|
||||
|
||||
void EventPropagationTestCase::ScrollWindowWithHandler()
|
||||
{
|
||||
TestWindow * const parent = new TestWindow(wxTheApp->GetTopWindow(), 'p');
|
||||
wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
|
||||
|
||||
TestScrollWindow * const win = new TestScrollWindow(parent);
|
||||
|
||||
#ifdef CAN_TEST_PAINT_EVENTS
|
||||
TestPaintEvtHandler h('h');
|
||||
win->PushEventHandler(&h);
|
||||
wxON_BLOCK_EXIT_OBJ1( *win, wxWindow::PopEventHandler, false );
|
||||
|
||||
win->GeneratePaintEvent();
|
||||
CPPUNIT_ASSERT_EQUAL( "ohPD", g_str );
|
||||
#endif
|
||||
|
||||
g_str.clear();
|
||||
wxCommandEvent eventCmd(TEST_EVT);
|
||||
win->HandleWindowEvent(eventCmd);
|
||||
CPPUNIT_ASSERT_EQUAL( "apA", g_str );
|
||||
}
|
||||
|
||||
#if wxUSE_MENUS
|
||||
|
||||
// Create a menu bar with a single menu containing wxID_APPLY menu item and
|
||||
// attach it to the specified frame.
|
||||
wxMenu* CreateTestMenu(wxFrame* frame)
|
||||
{
|
||||
wxMenu* const menu = new wxMenu;
|
||||
menu->Append(wxID_APPLY);
|
||||
#if wxUSE_MENUBAR
|
||||
wxMenuBar* const mb = new wxMenuBar;
|
||||
mb->Append(menu, "&Menu");
|
||||
frame->SetMenuBar(mb);
|
||||
#endif
|
||||
return menu;
|
||||
}
|
||||
|
||||
// Helper for checking that the menu event processing resulted in the expected
|
||||
// output from the handlers.
|
||||
//
|
||||
// Note that we trigger the menu event by sending it directly as this is more
|
||||
// reliable than using wxUIActionSimulator and currently works in all ports as
|
||||
// they all call wxMenuBase::SendEvent() from their respective menu event
|
||||
// handlers.
|
||||
#define ASSERT_MENU_EVENT_RESULT_FOR(cmd, menu, result) \
|
||||
g_str.clear(); \
|
||||
menu->SendEvent(cmd); \
|
||||
CHECK( g_str == result )
|
||||
|
||||
#define ASSERT_MENU_EVENT_RESULT(menu, result) \
|
||||
ASSERT_MENU_EVENT_RESULT_FOR(wxID_APPLY, menu, result)
|
||||
|
||||
void EventPropagationTestCase::MenuEvent()
|
||||
{
|
||||
wxFrame* const frame = static_cast<wxFrame*>(wxTheApp->GetTopWindow());
|
||||
|
||||
// Create a minimal menu bar.
|
||||
wxMenu* const menu = CreateTestMenu(frame);
|
||||
#if wxUSE_MENUBAR
|
||||
wxMenuBar* const mb = menu->GetMenuBar();
|
||||
std::unique_ptr<wxMenuBar> ensureMenuBarDestruction(mb);
|
||||
wxON_BLOCK_EXIT_OBJ1( *frame, wxFrame::SetMenuBar, (wxMenuBar*)nullptr );
|
||||
#endif
|
||||
// Check that wxApp gets the event exactly once.
|
||||
ASSERT_MENU_EVENT_RESULT( menu, "aA" );
|
||||
|
||||
|
||||
// Check that the menu event handler is called.
|
||||
TestMenuEvtHandler hm('m'); // 'm' for "menu"
|
||||
menu->SetNextHandler(&hm);
|
||||
wxON_BLOCK_EXIT_OBJ1( *menu,
|
||||
wxEvtHandler::SetNextHandler, (wxEvtHandler*)nullptr );
|
||||
ASSERT_MENU_EVENT_RESULT( menu, "aomA" );
|
||||
|
||||
|
||||
// Check that a handler can also be attached to a submenu.
|
||||
wxMenu* const submenu = new wxMenu;
|
||||
submenu->Append(wxID_ABOUT);
|
||||
menu->Append(wxID_ANY, "Submenu", submenu);
|
||||
|
||||
TestMenuEvtHandler hs('s'); // 's' for "submenu"
|
||||
submenu->SetNextHandler(&hs);
|
||||
wxON_BLOCK_EXIT_OBJ1( *submenu,
|
||||
wxEvtHandler::SetNextHandler, (wxEvtHandler*)nullptr );
|
||||
ASSERT_MENU_EVENT_RESULT_FOR( wxID_ABOUT, submenu, "aosomA" );
|
||||
|
||||
#if wxUSE_MENUBAR
|
||||
// Test that the event handler associated with the menu bar gets the event.
|
||||
TestMenuEvtHandler hb('b'); // 'b' for "menu Bar"
|
||||
mb->PushEventHandler(&hb);
|
||||
wxON_BLOCK_EXIT_OBJ1( *mb, wxWindow::PopEventHandler, false );
|
||||
|
||||
ASSERT_MENU_EVENT_RESULT( menu, "aomobA" );
|
||||
#endif
|
||||
|
||||
// Also test that the window to which the menu belongs gets the event.
|
||||
TestMenuEvtHandler hw('w'); // 'w' for "Window"
|
||||
frame->PushEventHandler(&hw);
|
||||
wxON_BLOCK_EXIT_OBJ1( *frame, wxWindow::PopEventHandler, false );
|
||||
|
||||
ASSERT_MENU_EVENT_RESULT( menu, "aomobowA" );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if wxUSE_DOC_VIEW_ARCHITECTURE
|
||||
|
||||
// Minimal viable implementations of wxDocument and wxView.
|
||||
class EventTestDocument : public wxDocument
|
||||
{
|
||||
public:
|
||||
EventTestDocument() { }
|
||||
|
||||
wxDECLARE_DYNAMIC_CLASS(EventTestDocument);
|
||||
};
|
||||
|
||||
class EventTestView : public wxView
|
||||
{
|
||||
public:
|
||||
EventTestView() { }
|
||||
|
||||
virtual void OnDraw(wxDC*) override { }
|
||||
|
||||
wxDECLARE_DYNAMIC_CLASS(EventTestView);
|
||||
};
|
||||
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(EventTestDocument, wxDocument);
|
||||
wxIMPLEMENT_DYNAMIC_CLASS(EventTestView, wxView);
|
||||
|
||||
void EventPropagationTestCase::DocView()
|
||||
{
|
||||
DocViewCommon(
|
||||
[](wxDocManager* manager,
|
||||
wxFrame *parent,
|
||||
wxWindowID id,
|
||||
const wxString& title) -> wxFrame*
|
||||
{
|
||||
return new wxDocMDIParentFrame(manager, parent, id, title);
|
||||
},
|
||||
[](wxDocument *doc,
|
||||
wxView *view,
|
||||
wxFrame *parent,
|
||||
wxWindowID id,
|
||||
const wxString& title) -> wxFrame*
|
||||
{
|
||||
wxDocMDIChildFrame* child = new wxDocMDIChildFrame(doc, view, dynamic_cast<wxDocMDIParentFrame*>(parent), id, title);
|
||||
// Ensure that the child that we've just created is the active one.
|
||||
child->Activate();
|
||||
return child;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#if wxUSE_AUI
|
||||
void EventPropagationTestCase::DocViewAui()
|
||||
{
|
||||
DocViewCommon(
|
||||
[](wxDocManager* manager,
|
||||
wxFrame *parent,
|
||||
wxWindowID id,
|
||||
const wxString& title) -> wxFrame*
|
||||
{
|
||||
class AuiParentFrame : public wxDocParentFrameAny<wxAuiMDIParentFrame>
|
||||
{
|
||||
public:
|
||||
AuiParentFrame(wxDocManager* manager,
|
||||
wxFrame* parent,
|
||||
wxWindowID id,
|
||||
const wxString& title) :
|
||||
wxDocParentFrameAny<wxAuiMDIParentFrame>(manager, parent, id, title),
|
||||
auiMgr(this)
|
||||
{
|
||||
}
|
||||
private:
|
||||
wxAuiManager auiMgr;
|
||||
};
|
||||
return new AuiParentFrame(manager, parent, id, title);
|
||||
},
|
||||
[](wxDocument *doc,
|
||||
wxView *view,
|
||||
wxFrame *parentBase,
|
||||
wxWindowID id,
|
||||
const wxString& title) -> wxFrame*
|
||||
{
|
||||
typedef wxDocParentFrameAny<wxAuiMDIParentFrame> ParentType;
|
||||
ParentType* parent = dynamic_cast<ParentType*>(parentBase);
|
||||
wxFrame* child = new wxDocChildFrameAny<wxAuiMDIChildFrame, wxAuiMDIParentFrame>(doc, view, parent, id, title);
|
||||
CHECK( parent->GetActiveChild() == child );
|
||||
return child;
|
||||
}
|
||||
);
|
||||
}
|
||||
#endif // wxUSE_AUI
|
||||
|
||||
void EventPropagationTestCase::DocViewCommon(wxFrame* (*newParent)(wxDocManager *manager,
|
||||
wxFrame *parent,
|
||||
wxWindowID id,
|
||||
const wxString& title),
|
||||
wxFrame* (*newChild)(wxDocument *doc,
|
||||
wxView *view,
|
||||
wxFrame *parent,
|
||||
wxWindowID id,
|
||||
const wxString& title))
|
||||
{
|
||||
// Set up the parent frame and its menu bar.
|
||||
wxDocManager docManager;
|
||||
|
||||
std::unique_ptr<wxFrame>
|
||||
parent((*newParent)(&docManager, nullptr, wxID_ANY, "Parent"));
|
||||
|
||||
wxMenu* const menu = CreateTestMenu(parent.get());
|
||||
|
||||
|
||||
// Set up the event handlers.
|
||||
TestEvtSink sinkDM('m');
|
||||
docManager.Connect(wxEVT_MENU,
|
||||
wxEventHandler(TestEvtSink::Handle), nullptr, &sinkDM);
|
||||
|
||||
TestEvtSink sinkParent('p');
|
||||
parent->Connect(wxEVT_MENU,
|
||||
wxEventHandler(TestEvtSink::Handle), nullptr, &sinkParent);
|
||||
|
||||
|
||||
// Check that wxDocManager and wxFrame get the event in order.
|
||||
ASSERT_MENU_EVENT_RESULT( menu, "ampA" );
|
||||
|
||||
|
||||
// The document template must be heap-allocated as wxDocManager owns it.
|
||||
wxDocTemplate* const docTemplate = new wxDocTemplate
|
||||
(
|
||||
&docManager, "Test", "", "", "",
|
||||
"Test Document", "Test View",
|
||||
wxCLASSINFO(EventTestDocument),
|
||||
wxCLASSINFO(EventTestView)
|
||||
);
|
||||
|
||||
// Now check what happens if we have an active document.
|
||||
wxDocument* const doc = docTemplate->CreateDocument("");
|
||||
wxView* const view = doc->GetFirstView();
|
||||
|
||||
std::unique_ptr<wxFrame>
|
||||
child((*newChild)(doc, view, parent.get(), wxID_ANY, "Child"));
|
||||
|
||||
wxMenu* const menuChild = CreateTestMenu(child.get());
|
||||
|
||||
// There are a lot of hacks related to child frame menu bar handling in
|
||||
// wxGTK and, in particular, the code in src/gtk/mdi.cpp relies on getting
|
||||
// idle events to really put everything in place. Moreover, as wxGTK uses
|
||||
// GtkNotebook as its MDI pages container, the frame must be shown for all
|
||||
// this to work as gtk_notebook_set_current_page() doesn't do anything if
|
||||
// called for a hidden window (this incredible fact cost me quite some time
|
||||
// to find empirically -- only to notice its confirmation in GTK+
|
||||
// documentation immediately afterwards). So just do whatever it takes to
|
||||
// make things work "as usual".
|
||||
child->Show();
|
||||
parent->Show();
|
||||
child->SetFocus(); // Without this, the test would fail on wxGTK2
|
||||
YieldForAWhile();
|
||||
|
||||
TestEvtSink sinkDoc('d');
|
||||
doc->Connect(wxEVT_MENU,
|
||||
wxEventHandler(TestEvtSink::Handle), nullptr, &sinkDoc);
|
||||
|
||||
TestEvtSink sinkView('v');
|
||||
view->Connect(wxEVT_MENU,
|
||||
wxEventHandler(TestEvtSink::Handle), nullptr, &sinkView);
|
||||
|
||||
TestEvtSink sinkChild('c');
|
||||
child->Connect(wxEVT_MENU,
|
||||
wxEventHandler(TestEvtSink::Handle), nullptr, &sinkChild);
|
||||
|
||||
// Check that wxDocument, wxView, wxDocManager, child frame and the parent
|
||||
// get the event in order.
|
||||
#if wxUSE_UIACTIONSIMULATOR
|
||||
// We use wxUIActionSimulator instead of ASSERT_MENU_EVENT_RESULT because
|
||||
// using the latter fails with wxQt on Linux.
|
||||
wxUnusedVar(menuChild);
|
||||
g_str.clear();
|
||||
|
||||
wxUIActionSimulator sim;
|
||||
sim.Char('m', wxMOD_ALT);
|
||||
// N.B.: Don't call wxYield() here, as this will cause the menu to appear
|
||||
// immediately (and enter its internal message loop) and the next line will
|
||||
// never be executed under wxMSW. In other words, the execution would block
|
||||
// indefinitely.
|
||||
sim.Char('a');
|
||||
wxYield();
|
||||
|
||||
CHECK( g_str == "advmcpA" );
|
||||
#else // !wxUSE_UIACTIONSIMULATOR
|
||||
ASSERT_MENU_EVENT_RESULT( menuChild, "advmcpA" );
|
||||
#endif // wxUSE_UIACTIONSIMULATOR
|
||||
|
||||
#if wxUSE_TOOLBAR
|
||||
// Also check that toolbar events get forwarded to the active child.
|
||||
wxToolBar* const tb = parent->CreateToolBar(wxTB_NOICONS);
|
||||
tb->AddTool(wxID_APPLY, "Apply", wxNullBitmap);
|
||||
tb->Realize();
|
||||
|
||||
// As in CheckMenuEvent(), use toolbar method actually sending the event
|
||||
// instead of bothering with wxUIActionSimulator which would have been
|
||||
// trickier.
|
||||
g_str.clear();
|
||||
tb->OnLeftClick(wxID_APPLY, true /* doesn't matter */);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL( "advmcpA", g_str );
|
||||
#endif // wxUSE_TOOLBAR
|
||||
}
|
||||
#endif // wxUSE_DOC_VIEW_ARCHITECTURE
|
||||
|
||||
#if wxUSE_UIACTIONSIMULATOR
|
||||
|
||||
class ContextMenuTestWindow : public wxWindow
|
||||
{
|
||||
public:
|
||||
ContextMenuTestWindow(wxWindow *parent, char tag)
|
||||
: wxWindow(parent, wxID_ANY),
|
||||
m_tag(tag)
|
||||
{
|
||||
Connect(wxEVT_CONTEXT_MENU,
|
||||
wxContextMenuEventHandler(ContextMenuTestWindow::OnMenu));
|
||||
}
|
||||
|
||||
private:
|
||||
void OnMenu(wxContextMenuEvent& event)
|
||||
{
|
||||
g_str += m_tag;
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
const char m_tag;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(ContextMenuTestWindow);
|
||||
};
|
||||
|
||||
void EventPropagationTestCase::ContextMenuEvent()
|
||||
{
|
||||
ContextMenuTestWindow * const
|
||||
parent = new ContextMenuTestWindow(wxTheApp->GetTopWindow(), 'p');
|
||||
wxON_BLOCK_EXIT_OBJ0( *parent, wxWindow::Destroy );
|
||||
|
||||
ContextMenuTestWindow * const
|
||||
child = new ContextMenuTestWindow(parent, 'c');
|
||||
parent->SetSize(100, 100);
|
||||
child->SetSize(0, 0, 50, 50);
|
||||
child->SetFocus();
|
||||
|
||||
wxUIActionSimulator sim;
|
||||
const wxPoint origin = parent->ClientToScreen(wxPoint(0, 0));
|
||||
|
||||
// Right clicking in the child should generate an event for it and the
|
||||
// parent.
|
||||
g_str.clear();
|
||||
sim.MouseMove(origin + wxPoint(10, 10));
|
||||
sim.MouseClick(wxMOUSE_BTN_RIGHT);
|
||||
|
||||
// At least with MSW, for WM_CONTEXTMENU to be synthesized by the system
|
||||
// from the right mouse click event, we must dispatch the mouse messages.
|
||||
wxYield();
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL( "cp", g_str );
|
||||
|
||||
// For some unfathomable reason the test below sporadically fails in wxGTK
|
||||
// buildbot builds, so disable it there to avoid spurious failure reports.
|
||||
#ifdef __WXGTK__
|
||||
if ( IsAutomaticTest() )
|
||||
return;
|
||||
#endif // __WXGTK__
|
||||
|
||||
// Right clicking outside the child should generate the event just in the
|
||||
// parent.
|
||||
g_str.clear();
|
||||
sim.MouseMove(origin + wxPoint(60, 60));
|
||||
sim.MouseClick(wxMOUSE_BTN_RIGHT);
|
||||
wxYield();
|
||||
CPPUNIT_ASSERT_EQUAL( "p", g_str );
|
||||
}
|
||||
|
||||
// Helper function: get the event propagation level.
|
||||
int GetPropagationLevel(wxEvent& e)
|
||||
{
|
||||
const int level = e.StopPropagation();
|
||||
e.ResumePropagation(level);
|
||||
return level;
|
||||
}
|
||||
|
||||
void EventPropagationTestCase::PropagationLevel()
|
||||
{
|
||||
wxSizeEvent se;
|
||||
CPPUNIT_ASSERT_EQUAL( GetPropagationLevel(se), (int)wxEVENT_PROPAGATE_NONE );
|
||||
|
||||
wxCommandEvent ce;
|
||||
CPPUNIT_ASSERT_EQUAL( GetPropagationLevel(ce), (int)wxEVENT_PROPAGATE_MAX );
|
||||
|
||||
wxCommandEvent ce2(ce);
|
||||
CPPUNIT_ASSERT_EQUAL( GetPropagationLevel(ce2), (int)wxEVENT_PROPAGATE_MAX );
|
||||
|
||||
wxCommandEvent ce3;
|
||||
ce3.ResumePropagation(17);
|
||||
CPPUNIT_ASSERT_EQUAL( GetPropagationLevel(ce3), 17 );
|
||||
|
||||
wxCommandEvent ce4(ce3);
|
||||
CPPUNIT_ASSERT_EQUAL( GetPropagationLevel(ce4), 17 );
|
||||
}
|
||||
|
||||
#endif // wxUSE_UIACTIONSIMULATOR
|
||||
169
libs/wxWidgets-3.3.1/tests/events/stopwatch.cpp
Normal file
169
libs/wxWidgets-3.3.1/tests/events/stopwatch.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: tests/events/stopwatch.cpp
|
||||
// Purpose: Test wxStopWatch class
|
||||
// Author: Francesco Montorsi (extracted from console sample)
|
||||
// Created: 2010-05-16
|
||||
// Copyright: (c) 2010 wxWidgets team
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "testprec.h"
|
||||
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#endif // WX_PRECOMP
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "wx/stopwatch.h"
|
||||
#include "wx/utils.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
const long tolerance = 50; // in ms
|
||||
const int sleepTime = 500;
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// test class
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
class StopWatchTestCase : public CppUnit::TestCase
|
||||
{
|
||||
public:
|
||||
StopWatchTestCase() {}
|
||||
|
||||
private:
|
||||
CPPUNIT_TEST_SUITE( StopWatchTestCase );
|
||||
CPPUNIT_TEST( Misc );
|
||||
CPPUNIT_TEST( BackwardsClockBug );
|
||||
CPPUNIT_TEST( RestartBug );
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
void Misc();
|
||||
void BackwardsClockBug();
|
||||
void RestartBug();
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(StopWatchTestCase);
|
||||
};
|
||||
|
||||
// register in the unnamed registry so that these tests are run by default
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION( StopWatchTestCase );
|
||||
|
||||
// also include in its own registry so that these tests can be run alone
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( StopWatchTestCase, "StopWatchTestCase" );
|
||||
|
||||
void StopWatchTestCase::Misc()
|
||||
{
|
||||
// Buildbot machines are quite slow and sleep doesn't work reliably there,
|
||||
// i.e. it can sleep for much longer than requested. This is not really an
|
||||
// error, so just don't run this test there -- and if you get failures in
|
||||
// this test when running it interactively, this might also be normal if
|
||||
// the machine is under heavy load.
|
||||
if ( IsAutomaticTest() )
|
||||
return;
|
||||
|
||||
wxStopWatch sw;
|
||||
long t;
|
||||
wxLongLong usec;
|
||||
|
||||
sw.Pause(); // pause it immediately
|
||||
|
||||
// verify that almost no time elapsed
|
||||
usec = sw.TimeInMicro();
|
||||
WX_ASSERT_MESSAGE
|
||||
(
|
||||
("Elapsed time was %" wxLongLongFmtSpec "dus", usec),
|
||||
usec < tolerance*1000
|
||||
);
|
||||
|
||||
wxSleep(1);
|
||||
t = sw.Time();
|
||||
|
||||
// check that the stop watch doesn't advance while paused
|
||||
WX_ASSERT_MESSAGE
|
||||
(
|
||||
("Actual time value is %ld", t),
|
||||
t >= 0 && t < tolerance
|
||||
);
|
||||
|
||||
sw.Resume();
|
||||
wxMilliSleep(sleepTime);
|
||||
t = sw.Time();
|
||||
// check that it did advance now by ~1.5s
|
||||
WX_ASSERT_MESSAGE
|
||||
(
|
||||
("Actual time value is %ld", t),
|
||||
t > sleepTime - tolerance && t < 2*sleepTime
|
||||
);
|
||||
|
||||
sw.Pause();
|
||||
|
||||
// check that this sleep won't be taken into account below
|
||||
wxMilliSleep(sleepTime);
|
||||
sw.Resume();
|
||||
|
||||
wxMilliSleep(sleepTime);
|
||||
t = sw.Time();
|
||||
|
||||
// and it should advance again
|
||||
WX_ASSERT_MESSAGE
|
||||
(
|
||||
("Actual time value is %ld", t),
|
||||
t > 2*sleepTime - tolerance && t < 3*sleepTime
|
||||
);
|
||||
}
|
||||
|
||||
void StopWatchTestCase::BackwardsClockBug()
|
||||
{
|
||||
wxStopWatch sw;
|
||||
wxStopWatch sw2;
|
||||
|
||||
for ( size_t n = 0; n < 10; n++ )
|
||||
{
|
||||
sw2.Start();
|
||||
|
||||
for ( size_t m = 0; m < 10000; m++ )
|
||||
{
|
||||
CPPUNIT_ASSERT( sw.Time() >= 0 );
|
||||
CPPUNIT_ASSERT( sw2.Time() >= 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StopWatchTestCase::RestartBug()
|
||||
{
|
||||
wxStopWatch sw;
|
||||
sw.Pause();
|
||||
|
||||
// Calling Start() should resume the stopwatch if it was paused.
|
||||
static const int offset = 5000;
|
||||
sw.Start(offset);
|
||||
wxMilliSleep(sleepTime);
|
||||
|
||||
long t = sw.Time();
|
||||
WX_ASSERT_MESSAGE
|
||||
(
|
||||
("Actual time value is %ld", t),
|
||||
t >= offset + sleepTime - tolerance
|
||||
);
|
||||
|
||||
// As above, this is not actually due to the fact of the test being
|
||||
// automatic but just because buildbot machines are usually pretty slow, so
|
||||
// this test often fails there simply because of the high load on them.
|
||||
if ( !IsAutomaticTest() )
|
||||
{
|
||||
|
||||
WX_ASSERT_MESSAGE
|
||||
(
|
||||
("Actual time value is %ld", t),
|
||||
t < offset + sleepTime + tolerance
|
||||
);
|
||||
}
|
||||
}
|
||||
139
libs/wxWidgets-3.3.1/tests/events/timertest.cpp
Normal file
139
libs/wxWidgets-3.3.1/tests/events/timertest.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: tests/events/timertest.cpp
|
||||
// Purpose: Test wxTimer events
|
||||
// Author: Vadim Zeitlin
|
||||
// Created: 2008-10-22
|
||||
// Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "testprec.h"
|
||||
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#endif // WX_PRECOMP
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "wx/evtloop.h"
|
||||
#include "wx/timer.h"
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// helper class counting the number of timer events
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
class TimerCounterHandler : public wxEvtHandler
|
||||
{
|
||||
public:
|
||||
TimerCounterHandler()
|
||||
{
|
||||
m_events = 0;
|
||||
|
||||
Connect(wxEVT_TIMER, wxTimerEventHandler(TimerCounterHandler::OnTimer));
|
||||
}
|
||||
|
||||
int GetNumEvents() const { return m_events; }
|
||||
|
||||
private:
|
||||
void OnTimer(wxTimerEvent& WXUNUSED(event))
|
||||
{
|
||||
m_events++;
|
||||
|
||||
Tick();
|
||||
}
|
||||
|
||||
virtual void Tick() { /* nothing to do in the base class */ }
|
||||
|
||||
int m_events;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(TimerCounterHandler);
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// test class
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
class TimerEventTestCase : public CppUnit::TestCase
|
||||
{
|
||||
public:
|
||||
TimerEventTestCase() {}
|
||||
|
||||
private:
|
||||
CPPUNIT_TEST_SUITE( TimerEventTestCase );
|
||||
CPPUNIT_TEST( OneShot );
|
||||
CPPUNIT_TEST( Multiple );
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
void OneShot();
|
||||
void Multiple();
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(TimerEventTestCase);
|
||||
};
|
||||
|
||||
// register in the unnamed registry so that these tests are run by default
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION( TimerEventTestCase );
|
||||
|
||||
// also include in its own registry so that these tests can be run alone
|
||||
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( TimerEventTestCase, "TimerEventTestCase" );
|
||||
|
||||
void TimerEventTestCase::OneShot()
|
||||
{
|
||||
class ExitOnTimerHandler : public TimerCounterHandler
|
||||
{
|
||||
public:
|
||||
ExitOnTimerHandler(wxEventLoopBase& loop)
|
||||
: TimerCounterHandler(),
|
||||
m_loop(loop)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void Tick() override { m_loop.Exit(); }
|
||||
|
||||
wxEventLoopBase& m_loop;
|
||||
|
||||
// don't use wxDECLARE_NO_COPY_CLASS() to avoid upsetting MSVC
|
||||
};
|
||||
|
||||
wxEventLoop loop;
|
||||
|
||||
ExitOnTimerHandler handler(loop);
|
||||
wxTimer timer(&handler);
|
||||
timer.Start(200, true);
|
||||
|
||||
loop.Run();
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL( 1, handler.GetNumEvents() );
|
||||
}
|
||||
|
||||
void TimerEventTestCase::Multiple()
|
||||
{
|
||||
wxEventLoop loop;
|
||||
|
||||
TimerCounterHandler handler;
|
||||
wxTimer timer(&handler);
|
||||
timer.Start(100);
|
||||
|
||||
// run the loop for 2 seconds
|
||||
time_t t;
|
||||
time(&t);
|
||||
const time_t tEnd = t + 2;
|
||||
while ( time(&t) < tEnd )
|
||||
{
|
||||
loop.Dispatch();
|
||||
}
|
||||
|
||||
// we can't count on getting exactly 20 ticks but we shouldn't get more
|
||||
// than this
|
||||
const int numTicks = handler.GetNumEvents();
|
||||
CPPUNIT_ASSERT( numTicks <= 20 );
|
||||
|
||||
// and we should get a decent number of them but if the system is very
|
||||
// loaded (as happens with build bot slaves running a couple of builds in
|
||||
// parallel actually) it may be much less than 20 so just check that we get
|
||||
// more than one
|
||||
CPPUNIT_ASSERT( numTicks > 1 );
|
||||
}
|
||||
Reference in New Issue
Block a user