Prevent duplicate menu event processing in MDI windows.
Record the object propagating the given event upwards in the event object itself and use it in wxMDIParentFrame to determine whether the event being handled is already coming from wxMDIChildFrame and avoid sending it back for processing it there again in this case. This is ugly and makes wx event processing even more complex but this is the only way I could find to ensure that (a) Both the child and the parent frames get the events from the toolbar (even though the toolbar parent is the parent frame and hence normally the child wouldn't get notified about them at all and so the forwarding at wxMDIParentFrame level is required to make this work). (b) The child gets the event only once, whether it comes from a toolbar (and hence indirectly via the parent frame) or from the child menu (and hence directly to the child, at least in wxMSW). This commit fixes the event propagation unit test case, at least under MSW and GTK. See #14314. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74357 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
12ab6ad3d2
commit
5ac5e40e41
@ -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);
|
||||
};
|
||||
|
@ -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<wxWindow*>(event.GetPropagatedFrom());
|
||||
if ( !from || !from->IsDescendant(child) )
|
||||
{
|
||||
if ( child->ProcessWindowEventLocally(event) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wxFrame::TryBefore(event);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user