diff --git a/include/wx/event.h b/include/wx/event.h index 38303aaae6..874d42e274 100644 --- a/include/wx/event.h +++ b/include/wx/event.h @@ -986,6 +986,9 @@ public: m_propagationLevel = propagationLevel; } + // This method is for internal use only and allows to get the object that + // is propagating this event upwards the window hierarchy, if any. + wxEvtHandler* GetPropagatedFrom() const { return m_propagatedFrom; } // This is for internal use only and is only called by // wxEvtHandler::ProcessEvent() to check whether it's the first time this @@ -1056,6 +1059,10 @@ protected: // the parent window (if any) int m_propagationLevel; + // The object that the event is being propagated from, initially NULL and + // only set by wxPropagateOnce. + wxEvtHandler* m_propagatedFrom; + bool m_skipped; bool m_isCommandEvent; @@ -1075,7 +1082,7 @@ protected: wxEvent& operator=(const wxEvent&); // for derived classes operator=() private: - // it needs to access our m_propagationLevel + // It needs to access our m_propagationLevel and m_propagatedFrom fields. friend class WXDLLIMPEXP_FWD_BASE wxPropagateOnce; // and this one needs to access our m_handlerToProcessOnlyIn @@ -1109,26 +1116,35 @@ private: }; /* - * Another one to temporarily lower propagation level. + * Helper used to indicate that an event is propagated upwards the window + * hierarchy by the given window. */ class WXDLLIMPEXP_BASE wxPropagateOnce { public: - wxPropagateOnce(wxEvent& event) : m_event(event) + // The handler argument should normally be non-NULL to allow the parent + // event handler to know that it's being used to process an event coming + // from the child, it's only NULL by default for backwards compatibility. + wxPropagateOnce(wxEvent& event, wxEvtHandler* handler = NULL) + : m_event(event), + m_propagatedFromOld(event.m_propagatedFrom) { wxASSERT_MSG( m_event.m_propagationLevel > 0, wxT("shouldn't be used unless ShouldPropagate()!") ); m_event.m_propagationLevel--; + m_event.m_propagatedFrom = handler; } ~wxPropagateOnce() { + m_event.m_propagatedFrom = m_propagatedFromOld; m_event.m_propagationLevel++; } private: wxEvent& m_event; + wxEvtHandler* const m_propagatedFromOld; wxDECLARE_NO_COPY_CLASS(wxPropagateOnce); }; diff --git a/include/wx/mdi.h b/include/wx/mdi.h index 78c2f4c3e4..52cbed7da4 100644 --- a/include/wx/mdi.h +++ b/include/wx/mdi.h @@ -381,8 +381,18 @@ inline bool wxMDIParentFrameBase::TryBefore(wxEvent& event) event.GetEventType() == wxEVT_UPDATE_UI ) { wxMDIChildFrame * const child = GetActiveChild(); - if ( child && child->ProcessWindowEventLocally(event) ) - return true; + if ( child ) + { + // However avoid sending the event back to the child if it's + // currently being propagated to us from it. + wxWindow* const + from = static_cast(event.GetPropagatedFrom()); + if ( !from || !from->IsDescendant(child) ) + { + if ( child->ProcessWindowEventLocally(event) ) + return true; + } + } } return wxFrame::TryBefore(event); diff --git a/src/common/event.cpp b/src/common/event.cpp index 2733450352..c9e8f11bca 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -369,6 +369,7 @@ wxEvent::wxEvent(int theId, wxEventType commandType) m_handlerToProcessOnlyIn = NULL; m_isCommandEvent = false; m_propagationLevel = wxEVENT_PROPAGATE_NONE; + m_propagatedFrom = NULL; m_wasProcessed = false; m_willBeProcessedAgain = false; } @@ -382,6 +383,7 @@ wxEvent::wxEvent(const wxEvent& src) , m_callbackUserData(src.m_callbackUserData) , m_handlerToProcessOnlyIn(NULL) , m_propagationLevel(src.m_propagationLevel) + , m_propagatedFrom(NULL) , m_skipped(src.m_skipped) , m_isCommandEvent(src.m_isCommandEvent) , m_wasProcessed(false) @@ -400,6 +402,7 @@ wxEvent& wxEvent::operator=(const wxEvent& src) m_callbackUserData = src.m_callbackUserData; m_handlerToProcessOnlyIn = NULL; m_propagationLevel = src.m_propagationLevel; + m_propagatedFrom = NULL; m_skipped = src.m_skipped; m_isCommandEvent = src.m_isCommandEvent; diff --git a/src/common/wincmn.cpp b/src/common/wincmn.cpp index 3c2c0f4e1d..787d08b13f 100644 --- a/src/common/wincmn.cpp +++ b/src/common/wincmn.cpp @@ -3370,7 +3370,7 @@ bool wxWindowBase::TryAfter(wxEvent& event) wxWindow *parent = GetParent(); if ( parent && !parent->IsBeingDeleted() ) { - wxPropagateOnce propagateOnce(event); + wxPropagateOnce propagateOnce(event, this); return parent->GetEventHandler()->ProcessEvent(event); }