From: Vadim Zeitlin Date: Thu, 20 May 2010 17:33:26 +0000 (+0000) Subject: Fix wxScrollHelperEvtHandler broken by recent changes to event processing. X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/ce45133ee7de9002d7fa274cbce6fc5cfab2d4c2 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 --- diff --git a/src/generic/scrlwing.cpp b/src/generic/scrlwing.cpp index 6e0cca186f..bc1d5cdbde 100644 --- a/src/generic/scrlwing.cpp +++ b/src/generic/scrlwing.cpp @@ -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() diff --git a/tests/events/propagation.cpp b/tests/events/propagation.cpp index e240dd6e17..f27395f1a5 100644 --- a/tests/events/propagation.cpp +++ b/tests/events/propagation.cpp @@ -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 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(&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 +{ + TestEvtHandler(char tag) + : TestEvtHandlerBase(TEST_EVT, tag) + { + } +}; + +struct TestPaintEvtHandler : TestEvtHandlerBase +{ + TestPaintEvtHandler(char tag) + : TestEvtHandlerBase(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 ); +} +