ensure that ProcessEvent() is called for all the event handlers, not just the first one in event handlers list

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@58144 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2009-01-16 16:07:16 +00:00
parent 23efa4bfb9
commit 29de6f400c
2 changed files with 58 additions and 30 deletions

View File

@@ -718,7 +718,7 @@ public:
void Skip(bool skip = true) { m_skipped = skip; } void Skip(bool skip = true) { m_skipped = skip; }
bool GetSkipped() const { return m_skipped; } bool GetSkipped() const { return m_skipped; }
// this function is used to create a copy of the event polymorphically and // This function is used to create a copy of the event polymorphically and
// all derived classes must implement it because otherwise wxPostEvent() // all derived classes must implement it because otherwise wxPostEvent()
// for them wouldn't work (it needs to do a copy of the event) // for them wouldn't work (it needs to do a copy of the event)
virtual wxEvent *Clone() const = 0; virtual wxEvent *Clone() const = 0;
@@ -747,6 +747,20 @@ public:
m_propagationLevel = propagationLevel; m_propagationLevel = propagationLevel;
} }
// This is for internal use only and is only called by
// wxEvtHandler::ProcessEvent() to check whether it's the first time this
// event is being processed
bool WasProcessed()
{
if ( m_wasProcessed )
return true;
m_wasProcessed = true;
return false;
}
protected: protected:
wxObject* m_eventObject; wxObject* m_eventObject;
wxEventType m_eventType; wxEventType m_eventType;
@@ -768,6 +782,12 @@ protected:
bool m_skipped; bool m_skipped;
bool m_isCommandEvent; bool m_isCommandEvent;
// initially false but becomes true as soon as WasProcessed() is called for
// the first time, as this is done only by ProcessEvent() it explains the
// variable name: it becomes true after ProcessEvent() was called at least
// once for this event
bool m_wasProcessed;
protected: protected:
wxEvent(const wxEvent&); // for implementing Clone() wxEvent(const wxEvent&); // for implementing Clone()
wxEvent& operator=(const wxEvent&); // for derived classes operator=() wxEvent& operator=(const wxEvent&); // for derived classes operator=()
@@ -3081,12 +3101,7 @@ public:
void OnSinkDestroyed( wxEvtHandler *sink ); void OnSinkDestroyed( wxEvtHandler *sink );
// The method processing the event in this event handler (or rather in this // The method tries to process the event in this event handler.
// event handler chain as it also tries the next handler and so on), i.e.
// it returns true if we processed this event or false if we didn't but
// does not call TryParent() in the latter case. It also doesn't call
// wxApp::FilterEvent() before processing it, this is supposed to be done
// by the public ProcessEvent() only once for every event we handle.
// //
// It is meant to be called from ProcessEvent() only and is not virtual, // It is meant to be called from ProcessEvent() only and is not virtual,
// additional event handlers can be hooked into the normal event processing // additional event handlers can be hooked into the normal event processing

View File

@@ -352,6 +352,7 @@ wxEvent::wxEvent(int theId, wxEventType commandType )
m_callbackUserData = NULL; m_callbackUserData = NULL;
m_isCommandEvent = false; m_isCommandEvent = false;
m_propagationLevel = wxEVENT_PROPAGATE_NONE; m_propagationLevel = wxEVENT_PROPAGATE_NONE;
m_wasProcessed = false;
} }
wxEvent::wxEvent(const wxEvent& src) wxEvent::wxEvent(const wxEvent& src)
@@ -364,6 +365,7 @@ wxEvent::wxEvent(const wxEvent& src)
, m_propagationLevel(src.m_propagationLevel) , m_propagationLevel(src.m_propagationLevel)
, m_skipped(src.m_skipped) , m_skipped(src.m_skipped)
, m_isCommandEvent(src.m_isCommandEvent) , m_isCommandEvent(src.m_isCommandEvent)
, m_wasProcessed(false)
{ {
} }
@@ -380,6 +382,8 @@ wxEvent& wxEvent::operator=(const wxEvent& src)
m_skipped = src.m_skipped; m_skipped = src.m_skipped;
m_isCommandEvent = src.m_isCommandEvent; m_isCommandEvent = src.m_isCommandEvent;
// don't change m_wasProcessed
return *this; return *this;
} }
@@ -1263,22 +1267,35 @@ bool wxEvtHandler::TryParent(wxEvent& event)
bool wxEvtHandler::ProcessEvent(wxEvent& event) bool wxEvtHandler::ProcessEvent(wxEvent& event)
{ {
// allow the application to hook into event processing // allow the application to hook into event processing
//
// note that we should only do it if we're the first event handler called
// to avoid calling FilterEvent() multiple times as the event goes through
// the event handler chain and possibly upwards the window hierarchy
if ( !event.WasProcessed() )
{
if ( wxTheApp ) if ( wxTheApp )
{ {
int rc = wxTheApp->FilterEvent(event); int rc = wxTheApp->FilterEvent(event);
if ( rc != -1 ) if ( rc != -1 )
{ {
wxASSERT_MSG( rc == 1 || rc == 0, wxASSERT_MSG( rc == 1 || rc == 0,
_T("unexpected wxApp::FilterEvent return value") ); "unexpected wxApp::FilterEvent return value" );
return rc != 0; return rc != 0;
} }
//else: proceed normally //else: proceed normally
} }
}
if ( ProcessEventHere(event) ) if ( ProcessEventHere(event) )
return true; return true;
// pass the event to the next handler, notice that we shouldn't call
// TryParent() even if it doesn't handle the event as the last handler in
// the chain will do it
if ( GetNextHandler() )
return GetNextHandler()->ProcessEvent(event);
// propagate the event upwards the window chain and/or to the application // propagate the event upwards the window chain and/or to the application
// object if it wasn't processed at this level // object if it wasn't processed at this level
return TryParent(event); return TryParent(event);
@@ -1286,11 +1303,12 @@ bool wxEvtHandler::ProcessEvent(wxEvent& event)
bool wxEvtHandler::ProcessEventHere(wxEvent& event) bool wxEvtHandler::ProcessEventHere(wxEvent& event)
{ {
// An event handler can be enabled or disabled // If the event handler is disabled it doesn't process any events
if ( GetEvtHandlerEnabled() ) if ( !GetEvtHandlerEnabled() )
{ return false;
// if we have a validator, it has higher priority than our own event
// table // If we have a validator, it has higher priority than our own event
// handlers
if ( TryValidator(event) ) if ( TryValidator(event) )
return true; return true;
@@ -1301,11 +1319,6 @@ bool wxEvtHandler::ProcessEventHere(wxEvent& event)
// Then static per-class event tables // Then static per-class event tables
if ( GetEventHashTable().HandleEvent(event, this) ) if ( GetEventHashTable().HandleEvent(event, this) )
return true; return true;
}
// Try going down the event handler chain
if ( GetNextHandler() && GetNextHandler()->ProcessEventHere(event) )
return true;
// We don't have a handler for this event. // We don't have a handler for this event.
return false; return false;