+ // 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 )
+ {
+ int rc = wxTheApp->FilterEvent(event);
+ if ( rc != -1 )
+ {
+ wxASSERT_MSG( rc == 1 || rc == 0,
+ "unexpected wxApp::FilterEvent return value" );
+
+ return rc != 0;
+ }
+ //else: proceed normally
+ }
+ }
+
+ if ( ProcessEventHere(event) )
+ return true;
+
+ // pass the event to the next handler, notice that we shouldn't call
+ // TryAfter() 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
+ // object if it wasn't processed at this level
+ return TryAfter(event);
+}
+
+bool wxEvtHandler::ProcessEventHere(wxEvent& event)
+{
+ // If the event handler is disabled it doesn't process any events
+ if ( !GetEvtHandlerEnabled() )
+ return false;
+
+ // Try the hooks which should be called before our own handlers
+ if ( TryBefore(event) )
+ return true;
+
+ // Handle per-instance dynamic event tables first
+ if ( m_dynamicEvents && SearchDynamicEventTable(event) )
+ return true;
+
+ // Then static per-class event tables
+ if ( GetEventHashTable().HandleEvent(event, this) )
+ return true;
+
+ // We don't have a handler for this event.
+ return false;
+}
+
+bool wxEvtHandler::SafelyProcessEvent(wxEvent& event)
+{
+#if wxUSE_EXCEPTIONS
+ try
+ {
+#endif
+ return ProcessEvent(event);
+#if wxUSE_EXCEPTIONS
+ }
+ catch ( ... )
+ {
+ // notice that we do it in 2 steps to avoid warnings about possibly
+ // uninitialized loop variable from some versions of g++ which are not
+ // smart enough to figure out that GetActive() doesn't throw and so
+ // that loop will always be initialized
+ wxEventLoopBase *loop = NULL;
+ try
+ {
+ loop = wxEventLoopBase::GetActive();
+
+ if ( !wxTheApp || !wxTheApp->OnExceptionInMainLoop() )
+ {
+ if ( loop )
+ loop->Exit();
+ }
+ //else: continue running current event loop
+
+ return false;
+ }
+ catch ( ... )
+ {
+ // OnExceptionInMainLoop() threw, possibly rethrowing the same
+ // exception again: very good, but we still need Exit() to
+ // be called
+ if ( loop )
+ loop->Exit();
+ throw;
+ }
+ }
+#endif // wxUSE_EXCEPTIONS
+}
+
+bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event)
+{
+ const wxEventType eventType = event.GetEventType();
+ for ( int i = 0; table.entries[i].m_fn != 0; i++ )
+ {
+ const wxEventTableEntry& entry = table.entries[i];
+ if ( eventType == entry.m_eventType )
+ {
+ if ( ProcessEventIfMatchesId(entry, this, event) )
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void wxEvtHandler::DoBind(int id,
+ int lastId,
+ wxEventType eventType,
+ wxEventFunctor *func,
+ wxObject *userData)
+{
+ wxDynamicEventTableEntry *entry =
+ new wxDynamicEventTableEntry(eventType, id, lastId, func, userData);
+
+ if (!m_dynamicEvents)
+ m_dynamicEvents = new wxList;
+
+ // Insert at the front of the list so most recent additions are found first
+ m_dynamicEvents->Insert( (wxObject*) entry );
+
+ // Make sure we get to know when a sink is destroyed
+ wxEvtHandler *eventSink = func->GetEvtHandler();
+ if ( eventSink && eventSink != this )
+ {
+ wxEventConnectionRef *evtConnRef = FindRefInTrackerList(eventSink);
+ if ( evtConnRef )
+ evtConnRef->IncRef( );
+ else
+ new wxEventConnectionRef(this, eventSink);
+ }
+}
+
+bool
+wxEvtHandler::DoUnbind(int id,
+ int lastId,
+ wxEventType eventType,
+ const wxEventFunctor& func,
+ wxObject *userData)
+{
+ if (!m_dynamicEvents)
+ return false;
+
+ // Remove connection from tracker node (wxEventConnectionRef)
+ wxEvtHandler *eventSink = func.GetEvtHandler();
+ if ( eventSink && eventSink != this )
+ {
+ wxEventConnectionRef *evtConnRef = FindRefInTrackerList(eventSink);
+ if ( evtConnRef )
+ evtConnRef->DecRef();
+ }
+
+ wxList::compatibility_iterator node = m_dynamicEvents->GetFirst();
+ while (node)
+ {
+ wxDynamicEventTableEntry *entry = (wxDynamicEventTableEntry*)node->GetData();
+
+ if ((entry->m_id == id) &&
+ ((entry->m_lastId == lastId) || (lastId == wxID_ANY)) &&
+ ((entry->m_eventType == eventType) || (eventType == wxEVT_NULL)) &&
+ entry->m_fn->IsMatching(func) &&
+ ((entry->m_callbackUserData == userData) || !userData))
+ {
+ delete entry->m_callbackUserData;
+ m_dynamicEvents->Erase( node );
+ delete entry;
+ return true;
+ }
+ node = node->GetNext();
+ }
+ return false;
+}
+
+bool wxEvtHandler::SearchDynamicEventTable( wxEvent& event )
+{
+ wxCHECK_MSG( m_dynamicEvents, false,
+ wxT("caller should check that we have dynamic events") );
+
+ wxList::compatibility_iterator node = m_dynamicEvents->GetFirst();
+ while (node)
+ {
+ wxDynamicEventTableEntry *entry = (wxDynamicEventTableEntry*)node->GetData();
+
+ // get next node before (maybe) calling the event handler as it could
+ // call Disconnect() invalidating the current node
+ node = node->GetNext();
+
+ if ( event.GetEventType() == entry->m_eventType )
+ {
+ wxEvtHandler *handler = entry->m_fn->GetEvtHandler();
+ if ( !handler )
+ handler = this;
+ if ( ProcessEventIfMatchesId(*entry, handler, event) )
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void wxEvtHandler::DoSetClientObject( wxClientData *data )
+{
+ wxASSERT_MSG( m_clientDataType != wxClientData_Void,
+ wxT("can't have both object and void client data") );
+
+ if ( m_clientObject )
+ delete m_clientObject;
+
+ m_clientObject = data;
+ m_clientDataType = wxClientData_Object;
+}
+
+wxClientData *wxEvtHandler::DoGetClientObject() const
+{
+ // it's not an error to call GetClientObject() on a window which doesn't
+ // have client data at all - NULL will be returned
+ wxASSERT_MSG( m_clientDataType != wxClientData_Void,
+ wxT("this window doesn't have object client data") );
+
+ return m_clientObject;
+}
+
+void wxEvtHandler::DoSetClientData( void *data )
+{
+ wxASSERT_MSG( m_clientDataType != wxClientData_Object,
+ wxT("can't have both object and void client data") );
+
+ m_clientData = data;
+ m_clientDataType = wxClientData_Void;
+}
+
+void *wxEvtHandler::DoGetClientData() const
+{
+ // it's not an error to call GetClientData() on a window which doesn't have
+ // client data at all - NULL will be returned
+ wxASSERT_MSG( m_clientDataType != wxClientData_Object,
+ wxT("this window doesn't have void client data") );
+
+ return m_clientData;
+}
+
+// A helper to find an wxEventConnectionRef object
+wxEventConnectionRef *
+wxEvtHandler::FindRefInTrackerList(wxEvtHandler *eventSink)
+{
+ for ( wxTrackerNode *node = eventSink->GetFirst(); node; node = node->m_nxt )
+ {
+ // we only want wxEventConnectionRef nodes here
+ wxEventConnectionRef *evtConnRef = node->ToEventConnection();
+ if ( evtConnRef && evtConnRef->m_src == this )
+ {
+ wxASSERT( evtConnRef->m_sink==eventSink );
+ return evtConnRef;
+ }
+ }
+
+ return NULL;
+}
+
+void wxEvtHandler::OnSinkDestroyed( wxEvtHandler *sink )
+{
+ wxASSERT(m_dynamicEvents);
+
+ // remove all connections with this sink
+ wxList::compatibility_iterator node = m_dynamicEvents->GetFirst(), node_nxt;
+ while (node)
+ {
+ wxDynamicEventTableEntry *entry = (wxDynamicEventTableEntry*)node->GetData();
+ node_nxt = node->GetNext();
+
+ if ( entry->m_fn->GetEvtHandler() == sink )
+ {
+ delete entry->m_callbackUserData;
+ m_dynamicEvents->Erase( node );
+ delete entry;
+ }
+ node = node_nxt;
+ }
+}
+
+#endif // wxUSE_BASE
+
+#if wxUSE_GUI
+
+// Find a window with the focus, that is also a descendant of the given window.
+// This is used to determine the window to initially send commands to.
+wxWindow* wxFindFocusDescendant(wxWindow* ancestor)
+{
+ // Process events starting with the window with the focus, if any.
+ wxWindow* focusWin = wxWindow::FindFocus();
+ wxWindow* win = focusWin;
+
+ // Check if this is a descendant of this frame.
+ // If not, win will be set to NULL.
+ while (win)
+ {
+ if (win == ancestor)
+ break;
+ else
+ win = win->GetParent();
+ }
+ if (win == NULL)
+ focusWin = NULL;
+
+ return focusWin;
+}
+
+// ----------------------------------------------------------------------------
+// wxEventBlocker
+// ----------------------------------------------------------------------------
+
+wxEventBlocker::wxEventBlocker(wxWindow *win, wxEventType type)
+{
+ wxCHECK_RET(win, wxT("Null window given to wxEventBlocker"));
+
+ m_window = win;
+
+ Block(type);
+ m_window->PushEventHandler(this);
+}
+
+wxEventBlocker::~wxEventBlocker()
+{
+ wxEvtHandler *popped = m_window->PopEventHandler(false);
+ wxCHECK_RET(popped == this,
+ wxT("Don't push other event handlers into a window managed by wxEventBlocker!"));
+}
+
+bool wxEventBlocker::ProcessEvent(wxEvent& event)
+{
+ // should this event be blocked?
+ for ( size_t i = 0; i < m_eventsToBlock.size(); i++ )
+ {
+ wxEventType t = (wxEventType)m_eventsToBlock[i];
+ if ( t == wxEVT_ANY || t == event.GetEventType() )
+ return true; // yes, it should: mark this event as processed
+ }
+
+ return false;