Fix wxScrollHelperEvtHandler broken by recent changes to event processing.

Use ProcessEventLocally() added in r64261 (which was probably the one to break
this) to forward event to the window itself instead of ProcessEvent() in
wxScrollHelperEvtHandler::ProcessEvent() implementation. Calling ProcessEvent()
didn't work any more in a case when another event handler was pushed on a
wxScrolledWindow: in this case the EVT_SIZE and EVT_PAINT handlers defined in
the window itself were not called at all any more.

Add a unit test checking for the even more tortuous than usual event
processing path in this particular case.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64358 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 2010-05-20 17:33:26 +00:00
parent 55a0f1e303
commit ce45133ee7
2 changed files with 90 additions and 9 deletions

View File

@ -204,7 +204,7 @@ bool wxScrollHelperEvtHandler::ProcessEvent(wxEvent& event)
m_hasDrawnWindow = true;
// pass it on to the real handler
bool processed = wxEvtHandler::ProcessEvent(event);
bool processed = m_nextHandler->ProcessEventLocally(event);
// always process the size events ourselves, even if the user code handles
// them as well, as we need to AdjustScrollbars()

View File

@ -20,6 +20,7 @@
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/event.h"
#include "wx/scrolwin.h"
#include "wx/window.h"
#endif // WX_PRECOMP
@ -34,37 +35,58 @@ wxString g_str;
// a custom event
wxDEFINE_EVENT(TEST_EVT, wxCommandEvent);
// a custom event handler
class TestEvtHandler : public wxEvtHandler
// a custom event handler tracing the propagation of the events of the
// specified types
template <class Event>
class TestEvtHandlerBase : public wxEvtHandler
{
public:
TestEvtHandler(char tag)
: m_tag(tag)
TestEvtHandlerBase(wxEventType evtType, char tag)
: m_evtType(evtType),
m_tag(tag)
{
Connect(TEST_EVT, wxCommandEventHandler(TestEvtHandler::OnTest));
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)
{
if ( event.GetEventType() == TEST_EVT )
if ( event.GetEventType() == m_evtType )
g_str += 'o'; // "o" == "overridden"
return wxEvtHandler::ProcessEvent(event);
}
private:
void OnTest(wxCommandEvent& event)
void OnTest(wxEvent& event)
{
g_str += m_tag;
event.Skip();
}
const wxEventType m_evtType;
const char m_tag;
DECLARE_NO_COPY_CLASS(TestEvtHandler)
wxDECLARE_NO_COPY_TEMPLATE_CLASS(TestEvtHandlerBase, Event);
};
struct TestEvtHandler : TestEvtHandlerBase<wxCommandEvent>
{
TestEvtHandler(char tag)
: TestEvtHandlerBase<wxCommandEvent>(TEST_EVT, tag)
{
}
};
struct TestPaintEvtHandler : TestEvtHandlerBase<wxPaintEvent>
{
TestPaintEvtHandler(char tag)
: TestEvtHandlerBase<wxPaintEvent>(wxEVT_PAINT, tag)
{
}
};
// a window handling the test event
@ -91,6 +113,35 @@ private:
DECLARE_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));
}
virtual void OnDraw(wxDC& WXUNUSED(dc))
{
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 )
@ -127,12 +178,16 @@ private:
CPPUNIT_TEST( TwoHandlers );
CPPUNIT_TEST( WindowWithoutHandler );
CPPUNIT_TEST( WindowWithHandler );
CPPUNIT_TEST( ScrollWindowWithoutHandler );
CPPUNIT_TEST( ScrollWindowWithHandler );
CPPUNIT_TEST_SUITE_END();
void OneHandler();
void TwoHandlers();
void WindowWithoutHandler();
void WindowWithHandler();
void ScrollWindowWithoutHandler();
void ScrollWindowWithHandler();
DECLARE_NO_COPY_CLASS(EventPropagationTestCase)
};
@ -207,3 +262,29 @@ void EventPropagationTestCase::WindowWithHandler()
CPPUNIT_ASSERT_EQUAL( "oa2o1cpA", g_str );
}
void EventPropagationTestCase::ScrollWindowWithoutHandler()
{
TestScrollWindow * const
win = new TestScrollWindow(wxTheApp->GetTopWindow());
wxON_BLOCK_EXIT_OBJ0( *win, wxWindow::Destroy );
wxPaintEvent event(win->GetId());
win->ProcessWindowEvent(event);
CPPUNIT_ASSERT_EQUAL( "PD", g_str );
}
void EventPropagationTestCase::ScrollWindowWithHandler()
{
TestScrollWindow * const
win = new TestScrollWindow(wxTheApp->GetTopWindow());
wxON_BLOCK_EXIT_OBJ0( *win, wxWindow::Destroy );
TestPaintEvtHandler h('h');
win->PushEventHandler(&h);
wxON_BLOCK_EXIT_OBJ1( *win, wxWindow::PopEventHandler, false );
wxPaintEvent event(win->GetId());
win->ProcessWindowEvent(event);
CPPUNIT_ASSERT_EQUAL( "ohPD", g_str );
}