From dc2513650dce762388f5469360cbb0ac84dcc2d0 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 15 Sep 2013 00:15:12 +0000 Subject: [PATCH] Propagate the event handling fixes to wxVarScrollHelperBase. Merge the fixes to wxScrollHelperBase::ProcessEvent() of r64358, r64370, r64464, r72939 and possibly a few more in wxVarScrollHelperBase to fix its behaviour too, as it wasn't generating the correct events any longer. Unfortunately the fix right now is to physically copy the code from one class to the other. This should be avoided, of course, and a more in depth refactoring should be done to move the code common to both classes into wxAnyScrollHelperBase after 3.0 release. But for now continuing to duplicate code is better than not having a working wxVarScrollHelperBase. See #15357. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74814 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/scrolwin.h | 15 +++++++---- include/wx/vscroll.h | 3 --- src/generic/scrlwing.cpp | 5 +++- src/generic/vscroll.cpp | 54 +++++++++++++++++++++++++++++++--------- 4 files changed, 56 insertions(+), 21 deletions(-) diff --git a/include/wx/scrolwin.h b/include/wx/scrolwin.h index 3e22eb59c2..3ea03fcc60 100644 --- a/include/wx/scrolwin.h +++ b/include/wx/scrolwin.h @@ -66,9 +66,19 @@ class WXDLLIMPEXP_CORE wxAnyScrollHelperBase public: wxEXPLICIT wxAnyScrollHelperBase(wxWindow* win); + // Override this function to draw the graphic (or just process EVT_PAINT) + virtual void OnDraw(wxDC& WXUNUSED(dc)) { } + + // change the DC origin according to the scroll position. + virtual void DoPrepareDC(wxDC& dc) = 0; + // Simple accessor for the window that is really being scrolled. wxWindow *GetTargetWindow() const { return m_targetWindow; } + + // The methods called from the window event handlers. + void HandleOnPaint(wxPaintEvent& event); + protected: // the window that receives the scroll events and the window to actually // scroll, respectively @@ -199,10 +209,6 @@ public: void SetTargetRect(const wxRect& rect) { m_rectToScroll = rect; } wxRect GetTargetRect() const { return m_rectToScroll; } - // Override this function to draw the graphic (or just process EVT_PAINT) - virtual void OnDraw(wxDC& WXUNUSED(dc)) { } - - // change the DC origin according to the scroll position. virtual void DoPrepareDC(wxDC& dc); // are we generating the autoscroll events? @@ -222,7 +228,6 @@ public: // the methods to be called from the window event handlers void HandleOnScroll(wxScrollWinEvent& event); void HandleOnSize(wxSizeEvent& event); - void HandleOnPaint(wxPaintEvent& event); void HandleOnChar(wxKeyEvent& event); void HandleOnMouseEnter(wxMouseEvent& event); void HandleOnMouseLeave(wxMouseEvent& event); diff --git a/include/wx/vscroll.h b/include/wx/vscroll.h index 51e2b0b58c..2312d78f0b 100644 --- a/include/wx/vscroll.h +++ b/include/wx/vscroll.h @@ -121,9 +121,6 @@ public: // scrollbars (spreadsheet: only cell area will move). virtual void SetTargetWindow(wxWindow *target); - // Override this function to draw the graphic (or just process EVT_PAINT) - //virtual void OnDraw(wxDC& WXUNUSED(dc)) { } - // change the DC origin according to the scroll position. To properly // forward calls to wxWindow::Layout use WX_FORWARD_TO_SCROLL_HELPER() // derived class diff --git a/src/generic/scrlwing.cpp b/src/generic/scrlwing.cpp index 1323e45060..5fb622b242 100644 --- a/src/generic/scrlwing.cpp +++ b/src/generic/scrlwing.cpp @@ -186,6 +186,9 @@ void wxAutoScrollTimer::Notify() // wxScrollHelperEvtHandler // ---------------------------------------------------------------------------- +// Notice that this method is currently duplicated in the method with the same +// name in wxVarScrollHelperEvtHandler class, until this is fixed, the other +// copy of the method needs to be modified every time this version is. bool wxScrollHelperEvtHandler::ProcessEvent(wxEvent& event) { wxEventType evType = event.GetEventType(); @@ -817,7 +820,7 @@ void wxScrollHelperBase::HandleOnSize(wxSizeEvent& WXUNUSED(event)) // This calls OnDraw, having adjusted the origin according to the current // scroll position -void wxScrollHelperBase::HandleOnPaint(wxPaintEvent& WXUNUSED(event)) +void wxAnyScrollHelperBase::HandleOnPaint(wxPaintEvent& WXUNUSED(event)) { // don't use m_targetWindow here, this is always called for ourselves wxPaintDC dc(m_win); diff --git a/src/generic/vscroll.cpp b/src/generic/vscroll.cpp index 905d7cc4d0..0048bd75b0 100644 --- a/src/generic/vscroll.cpp +++ b/src/generic/vscroll.cpp @@ -61,12 +61,20 @@ private: // wxVarScrollHelperEvtHandler implementation // ============================================================================ +// FIXME: This method totally duplicates a method with the same name in +// wxScrollHelperEvtHandler, we really should merge them by reusing the +// common parts in wxAnyScrollHelperBase. bool wxVarScrollHelperEvtHandler::ProcessEvent(wxEvent& event) { wxEventType evType = event.GetEventType(); - // pass it on to the real handler - bool processed = wxEvtHandler::ProcessEvent(event); + // Pass it on to the real handler: notice that we must not call + // ProcessEvent() on this object itself as it wouldn't pass it to the next + // handler (i.e. the real window) if we're called from a previous handler + // (as indicated by "process here only" flag being set) and we do want to + // execute the handler defined in the window we're associated with right + // now, without waiting until TryAfter() is called from wxEvtHandler. + bool processed = m_nextHandler->ProcessEvent(event); // always process the size events ourselves, even if the user code handles // them as well, as we need to AdjustScrollbars() @@ -78,18 +86,28 @@ bool wxVarScrollHelperEvtHandler::ProcessEvent(wxEvent& event) if ( evType == wxEVT_SIZE ) { m_scrollHelper->HandleOnSize((wxSizeEvent &)event); - - return !event.GetSkipped(); + return true; } - if ( processed ) + if ( processed && event.IsCommandEvent()) + return true; + + // For wxEVT_PAINT the user code can either handle this event as usual or + // override virtual OnDraw(), so if the event hasn't been handled we need + // to call this virtual function ourselves. + if ( +#ifndef __WXUNIVERSAL__ + // in wxUniversal "processed" will always be true, because + // all windows use the paint event to draw themselves. + // In this case we can't use this flag to determine if a custom + // paint event handler already drew our window and we just + // call OnDraw() anyway. + !processed && +#endif // !__WXUNIVERSAL__ + evType == wxEVT_PAINT ) { - // normally, nothing more to do here - except if we have a command - // event - if ( event.IsCommandEvent() ) - { - return true; - } + m_scrollHelper->HandleOnPaint((wxPaintEvent &)event); + return true; } // reset the skipped flag (which might have been set to true in @@ -112,7 +130,8 @@ bool wxVarScrollHelperEvtHandler::ProcessEvent(wxEvent& event) { // it makes sense to indicate that we processed the message as we // did scroll the window (and also notice that wxAutoScrollTimer - // relies on our return value for continuous scrolling) + // relies on our return value to stop scrolling when we are at top + // or bottom already) processed = true; wasSkipped = false; } @@ -126,6 +145,17 @@ bool wxVarScrollHelperEvtHandler::ProcessEvent(wxEvent& event) event.Skip(wasSkipped); + // We called ProcessEvent() on the next handler, meaning that we explicitly + // worked around the request to process the event in this handler only. As + // explained above, this is unfortunately really necessary but the trouble + // is that the event will continue to be post-processed by the previous + // handler resulting in duplicate calls to event handlers. Call the special + // function below to prevent this from happening, base class DoTryChain() + // will check for it and behave accordingly. + // + // And if we're not called from DoTryChain(), this won't do anything anyhow. + event.DidntHonourProcessOnlyIn(); + return processed; } -- 2.45.2