]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/event.cpp
reset the tooltip text before changing it, this apparently prevents a spurious redraw...
[wxWidgets.git] / src / common / event.cpp
index ce2a0815261caa50d60075b8bca6ef45b74338a3..af8b2ac1b2038cf41c96e046f7cb407c0aa23d23 100644 (file)
@@ -29,6 +29,7 @@
 
 #ifndef WX_PRECOMP
     #include "wx/list.h"
+    #include "wx/log.h"
     #include "wx/app.h"
     #include "wx/utils.h"
     #include "wx/stopwatch.h"
@@ -145,16 +146,6 @@ IMPLEMENT_DYNAMIC_CLASS(wxEventTableEntryModule, wxModule)
 // global variables
 // ----------------------------------------------------------------------------
 
-// List containing event handlers with pending events (each handler can occur
-// at most once here)
-wxList *wxHandlersWithPendingEvents = NULL;
-wxList *wxHandlersWithPendingDelayedEvents = NULL;
-
-#if wxUSE_THREADS
-    // protects wxHandlersWithPendingEvents list
-    wxCriticalSection *wxHandlersWithPendingEventsLocker = NULL;
-#endif
-
 // common event types are defined here, other event types are defined by the
 // components which use them
 
@@ -770,7 +761,6 @@ wxKeyEvent::wxKeyEvent(wxEventType type)
 {
     m_eventType = type;
     m_keyCode = 0;
-    m_scanCode = 0;
 #if wxUSE_UNICODE
     m_uniChar = 0;
 #endif
@@ -784,8 +774,6 @@ wxKeyEvent::wxKeyEvent(const wxKeyEvent& evt)
     m_y = evt.m_y;
 
     m_keyCode = evt.m_keyCode;
-
-    m_scanCode = evt.m_scanCode;
     m_rawCode = evt.m_rawCode;
     m_rawFlags = evt.m_rawFlags;
 
@@ -1037,10 +1025,6 @@ void wxEventHashTable::GrowEventTypeTable()
 // wxEvtHandler
 // ----------------------------------------------------------------------------
 
-/*
- * Event handler
- */
-
 wxEvtHandler::wxEvtHandler()
 {
     m_nextHandler = NULL;
@@ -1085,41 +1069,16 @@ wxEvtHandler::~wxEvtHandler()
             delete entry;
         }
         delete m_dynamicEvents;
-    };
+    }
 
     if (m_pendingEvents)
         m_pendingEvents->DeleteContents(true);
     delete m_pendingEvents;
 
-    // Remove us from wxHandlersWithPendingEvents if necessary.
-    if ( wxHandlersWithPendingEvents )
-    {
-#if wxUSE_THREADS
-        if (wxHandlersWithPendingEventsLocker)
-            wxENTER_CRIT_SECT(*wxHandlersWithPendingEventsLocker);
-#endif
-
-        if ( wxHandlersWithPendingEvents->DeleteObject(this) )
-        {
-            // check that we were present only once in the list
-            wxASSERT_MSG( !wxHandlersWithPendingEvents->Find(this),
-                          "Handler occurs twice in wxHandlersWithPendingEvents list" );
-        }
-        //else: we weren't in this list at all, it's ok
-
-        if ( wxHandlersWithPendingDelayedEvents->DeleteObject(this) )
-        {
-            // check that we were present only once in the list
-            wxASSERT_MSG( !wxHandlersWithPendingDelayedEvents->Find(this),
-                          "Handler occurs twice in wxHandlersWithPendingDelayedEvents list" );
-        }
-        //else: we weren't in this list at all, it's ok
-
-#if wxUSE_THREADS
-        if (wxHandlersWithPendingEventsLocker)
-            wxLEAVE_CRIT_SECT(*wxHandlersWithPendingEventsLocker);
-#endif
-    }
+    // Remove us from the list of the pending events if necessary.
+    wxEventLoopBase *loop = wxEventLoopBase::GetActive();
+    if (loop)
+        loop->RemovePendingEventHandler(this);
 
     // we only delete object data, not untyped
     if ( m_clientDataType == wxClientData_Object )
@@ -1165,6 +1124,19 @@ void wxEvtHandler::QueueEvent(wxEvent *event)
 {
     wxCHECK_RET( event, "NULL event can't be posted" );
 
+    wxEventLoopBase* loop = wxEventLoopBase::GetActive();
+    if (!loop)
+    {
+        // we need an event loop which manages the list of event handlers with
+        // pending events... cannot proceed without it!
+        wxLogDebug("No event loop is running! Cannot queue this event!");
+
+        // anyway delete the given event to avoid memory leaks
+        delete event;
+
+        return;
+    }
+
     // 1) Add this event to our list of pending events
     wxENTER_CRIT_SECT( m_pendingEventsLock );
 
@@ -1176,14 +1148,7 @@ void wxEvtHandler::QueueEvent(wxEvent *event)
     // 2) Add this event handler to list of event handlers that
     //    have pending events.
 
-    wxENTER_CRIT_SECT(*wxHandlersWithPendingEventsLocker);
-
-    if ( !wxHandlersWithPendingEvents )
-        wxHandlersWithPendingEvents = new wxList;
-    if ( !wxHandlersWithPendingEvents->Find(this) )
-        wxHandlersWithPendingEvents->Append(this);
-
-    wxLEAVE_CRIT_SECT(*wxHandlersWithPendingEventsLocker);
+    loop->AppendPendingEventHandler(this);
 
     // only release m_pendingEventsLock now because otherwise there is a race
     // condition as described in the ticket #9093: we could process the event
@@ -1200,6 +1165,15 @@ void wxEvtHandler::QueueEvent(wxEvent *event)
 
 void wxEvtHandler::ProcessPendingEvents()
 {
+    wxEventLoopBase* loop = wxEventLoopBase::GetActive();
+    if (!loop)
+    {
+        // we need an event loop which manages the list of event handlers with
+        // pending events... cannot proceed without it!
+        wxLogDebug("No event loop is running! Cannot process pending events!");
+        return;
+    }
+
     // we need to process only a single pending event in this call because
     // each call to ProcessEvent() could result in the destruction of this
     // same event handler (see the comment at the end of this function)
@@ -1215,9 +1189,10 @@ void wxEvtHandler::ProcessPendingEvents()
     wxEvent* pEvent = static_cast<wxEvent *>(node->GetData());
 
     // find the first event which can be processed now:
-    if (wxTheApp && wxTheApp->IsYielding())
+    wxEventLoopBase* evtLoop = wxEventLoopBase::GetActive();
+    if (evtLoop && evtLoop->IsYielding())
     {
-        while (node && pEvent && !wxTheApp->IsEventAllowedInsideYield(pEvent->GetEventCategory()))
+        while (node && pEvent && !evtLoop->IsEventAllowedInsideYield(pEvent->GetEventCategory()))
         {
             node = node->GetNext();
             pEvent = node ? static_cast<wxEvent *>(node->GetData()) : NULL;
@@ -1226,19 +1201,11 @@ void wxEvtHandler::ProcessPendingEvents()
         if (!node)
         {
             // all our events are NOT processable now... signal this:
-#if wxUSE_THREADS
-            if (wxHandlersWithPendingEventsLocker)
-                wxENTER_CRIT_SECT(*wxHandlersWithPendingEventsLocker);
-#endif
-            // move us from the list of handlers with processable pending events
-            // to the list of handlers with pending events which needs to be processed later
-            wxHandlersWithPendingEvents->DeleteObject(this);
-            if ( !wxHandlersWithPendingDelayedEvents->Find(this) )
-                wxHandlersWithPendingDelayedEvents->Append(this);
-#if wxUSE_THREADS
-            if (wxHandlersWithPendingEventsLocker)
-                wxLEAVE_CRIT_SECT(*wxHandlersWithPendingEventsLocker);
-#endif
+            loop->DelayPendingEventHandler(this);
+
+            // see the comment at the beginning of evtloop.h header for the
+            // logic behind YieldFor() and behind DelayPendingEventHandler()
+
             wxLEAVE_CRIT_SECT( m_pendingEventsLock );
 
             return;
@@ -1252,19 +1219,11 @@ void wxEvtHandler::ProcessPendingEvents()
     // same event again.
     m_pendingEvents->Erase(node);
 
-    // if there are no more pending events left, we don't need to stay in this
-    // list
     if ( m_pendingEvents->IsEmpty() )
     {
-#if wxUSE_THREADS
-        if (wxHandlersWithPendingEventsLocker)
-            wxENTER_CRIT_SECT(*wxHandlersWithPendingEventsLocker);
-#endif
-        wxHandlersWithPendingEvents->DeleteObject(this);
-#if wxUSE_THREADS
-        if (wxHandlersWithPendingEventsLocker)
-            wxLEAVE_CRIT_SECT(*wxHandlersWithPendingEventsLocker);
-#endif
+        // if there are no more pending events left, we don't need to
+        // stay in this list
+        loop->RemovePendingEventHandler(this);
     }
 
     wxLEAVE_CRIT_SECT( m_pendingEventsLock );
@@ -1320,15 +1279,8 @@ wxEvtHandler::ProcessEventIfMatchesId(const wxEventTableEntryBase& entry,
     return false;
 }
 
-bool wxEvtHandler::TryParent(wxEvent& event)
+bool wxEvtHandler::DoTryApp(wxEvent& event)
 {
-    if ( GetNextHandler() )
-    {
-        // the next handler will pass it to wxTheApp if it doesn't process it,
-        // so return from here to avoid doing it again
-        return GetNextHandler()->TryParent(event);
-    }
-
     if ( wxTheApp && (this != wxTheApp) )
     {
         // Special case: don't pass wxEVT_IDLE to wxApp, since it'll always
@@ -1344,6 +1296,27 @@ bool wxEvtHandler::TryParent(wxEvent& event)
     return false;
 }
 
+bool wxEvtHandler::TryBefore(wxEvent& event)
+{
+#ifdef WXWIN_COMPATIBILITY_2_8
+    // call the old virtual function to keep the code overriding it working
+    return TryValidator(event);
+#else
+    wxUnusedVar(event);
+    return false;
+#endif
+}
+
+bool wxEvtHandler::TryAfter(wxEvent& event)
+{
+#ifdef WXWIN_COMPATIBILITY_2_8
+    // as above, call the old virtual function for compatibility
+    return TryParent(event);
+#else
+    return DoTryApp(event);
+#endif
+}
+
 bool wxEvtHandler::ProcessEvent(wxEvent& event)
 {
     // allow the application to hook into event processing
@@ -1355,27 +1328,6 @@ bool wxEvtHandler::ProcessEvent(wxEvent& event)
     {
         if ( wxTheApp )
         {
-/*
-    CANNOT ENABLE: ProcessEvent() must always immediately process the event!
-
-            if (wxTheApp->IsYielding() &&
-                !wxTheApp->IsEventAllowedInsideYield(event.GetEventCategory()))
-            {
-                wxEvent* queuedEv = event.Clone();
-
-                // queue this event rather than processing it now
-                QueueEvent(queuedEv);
-                    // the wxWakeUpIdle call shouldn't probably be done
-                    // in this context (there's wxYield in the call stack)
-
-                return true;
-                    // it's not completely true that the event was processed;
-                    // but we cannot even say it was skipped or discarded...
-            }
-            //else: either we're not inside a wxYield() call or if we are,
-            //      we can process this event immediately.
-*/
-
             int rc = wxTheApp->FilterEvent(event);
             if ( rc != -1 )
             {
@@ -1392,14 +1344,14 @@ bool wxEvtHandler::ProcessEvent(wxEvent& event)
         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
+    // 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 TryParent(event);
+    return TryAfter(event);
 }
 
 bool wxEvtHandler::ProcessEventHere(wxEvent& event)
@@ -1408,9 +1360,8 @@ bool wxEvtHandler::ProcessEventHere(wxEvent& event)
     if ( !GetEvtHandlerEnabled() )
         return false;
 
-    // If we have a validator, it has higher priority than our own event
-    // handlers
-    if ( TryValidator(event) )
+    // Try the hooks which should be called before our own handlers
+    if ( TryBefore(event) )
         return true;
 
     // Handle per-instance dynamic event tables first