X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9b4da62701dbe8ccfbe447ce8d1bc77fcb40e9e5..cdfd5e01663ff0febc9630ac4cfa317841b4fb26:/src/common/appbase.cpp diff --git a/src/common/appbase.cpp b/src/common/appbase.cpp index 857b157822..a78e93d1d4 100644 --- a/src/common/appbase.cpp +++ b/src/common/appbase.cpp @@ -42,7 +42,7 @@ #include "wx/evtloop.h" #include "wx/filename.h" #include "wx/msgout.h" -#include "wx/ptr_scpd.h" +#include "wx/scopedptr.h" #include "wx/tokenzr.h" #include "wx/thread.h" @@ -63,19 +63,6 @@ #include "wx/fontmap.h" #endif // wxUSE_FONTMAP -#if defined(__DARWIN__) && defined(_MSL_USING_MW_C_HEADERS) && _MSL_USING_MW_C_HEADERS - // For MacTypes.h for Debugger function - #include -#endif - -#if defined(__WXMAC__) - #ifdef __DARWIN__ - #include - #else - #include "wx/mac/private.h" // includes mac headers - #endif -#endif // __WXMAC__ - #ifdef __WXDEBUG__ #if wxUSE_STACKWALKER #include "wx/stackwalk.h" @@ -124,6 +111,8 @@ wxAppConsole *wxAppConsoleBase::ms_appInstance = NULL; wxAppInitializerFunction wxAppConsoleBase::ms_appInitFn = NULL; +wxSocketManager *wxAppTraitsBase::ms_manager = NULL; + // ---------------------------------------------------------------------------- // wxEventLoopPtr // ---------------------------------------------------------------------------- @@ -144,7 +133,7 @@ wxAppConsoleBase::wxAppConsoleBase() m_traits = NULL; m_mainLoop = NULL; - ms_appInstance = wx_static_cast(wxAppConsole *, this); + ms_appInstance = static_cast(this); #ifdef __WXDEBUG__ SetTraceMasks(); @@ -164,25 +153,17 @@ wxAppConsoleBase::~wxAppConsoleBase() } // ---------------------------------------------------------------------------- -// initilization/cleanup +// initialization/cleanup // ---------------------------------------------------------------------------- -bool wxAppConsoleBase::Initialize(int& argcOrig, wxChar **argvOrig) +bool wxAppConsoleBase::Initialize(int& WXUNUSED(argc), wxChar **argv) { #if wxUSE_INTL GetTraits()->SetLocale(); #endif // wxUSE_INTL - // remember the command line arguments - argc = argcOrig; - argv = argvOrig; - -#if wxUSE_THREADS - wxPendingEventsLocker = new wxCriticalSection; -#endif - #ifndef __WXPALMOS__ - if ( m_appName.empty() && argv ) + if ( m_appName.empty() && argv && argv[0] ) { // the application name is, by default, the name of its executable file wxFileName::SplitPath(argv[0], NULL, &m_appName, NULL); @@ -204,14 +185,6 @@ void wxAppConsoleBase::CleanUp() delete m_mainLoop; m_mainLoop = NULL; } - - delete wxPendingEvents; - wxPendingEvents = NULL; - -#if wxUSE_THREADS - delete wxPendingEventsLocker; - wxPendingEventsLocker = NULL; -#endif // wxUSE_THREADS } // ---------------------------------------------------------------------------- @@ -258,7 +231,7 @@ int wxAppConsoleBase::OnExit() #if wxUSE_CONFIG // delete the config object if any (don't use Get() here, but Set() // because Get() could create a new config object) - delete wxConfigBase::Set((wxConfigBase *) NULL); + delete wxConfigBase::Set(NULL); #endif // wxUSE_CONFIG return 0; @@ -294,8 +267,15 @@ wxAppTraits *wxAppConsoleBase::GetTraits() return m_traits; } +/* static */ +wxAppTraits *wxAppConsoleBase::GetTraitsIfExists() +{ + wxAppConsole * const app = GetInstance(); + return app ? app->GetTraits() : NULL; +} + // ---------------------------------------------------------------------------- -// event processing +// wxEventLoop redirection // ---------------------------------------------------------------------------- int wxAppConsoleBase::MainLoop() @@ -333,17 +313,30 @@ bool wxAppConsoleBase::Dispatch() return loop && loop->Dispatch(); } -bool wxAppConsoleBase::HasPendingEvents() const +bool wxAppConsoleBase::Yield(bool onlyIfNeeded) { - wxENTER_CRIT_SECT( *wxPendingEventsLocker ); + wxEventLoopBase * const loop = wxEventLoopBase::GetActive(); - bool has = wxPendingEvents && !wxPendingEvents->IsEmpty(); + return loop && loop->Yield(onlyIfNeeded); +} + +void wxAppConsoleBase::WakeUpIdle() +{ + if ( m_mainLoop ) + m_mainLoop->WakeUp(); +} - wxLEAVE_CRIT_SECT( *wxPendingEventsLocker ); +bool wxAppConsoleBase::ProcessIdle() +{ + wxEventLoopBase * const loop = wxEventLoopBase::GetActive(); - return has; + return loop && loop->ProcessIdle(); } +// ---------------------------------------------------------------------------- +// events +// ---------------------------------------------------------------------------- + /* static */ bool wxAppConsoleBase::IsMainLoopRunning() { @@ -352,58 +345,121 @@ bool wxAppConsoleBase::IsMainLoopRunning() return app && app->m_mainLoop != NULL; } -void wxAppConsoleBase::ProcessPendingEvents() +int wxAppConsoleBase::FilterEvent(wxEvent& WXUNUSED(event)) { -#if wxUSE_THREADS - if ( !wxPendingEventsLocker ) - return; -#endif + // process the events normally by default + return -1; +} + +void wxAppConsoleBase::DelayPendingEventHandler(wxEvtHandler* toDelay) +{ + wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker); + + // move the handler from the list of handlers with processable pending events + // to the list of handlers with pending events which needs to be processed later + m_handlersWithPendingEvents.Remove(toDelay); - wxENTER_CRIT_SECT( *wxPendingEventsLocker ); + if (m_handlersWithPendingDelayedEvents.Index(toDelay) == wxNOT_FOUND) + m_handlersWithPendingDelayedEvents.Add(toDelay); - if (wxPendingEvents) + wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker); +} + +void wxAppConsoleBase::RemovePendingEventHandler(wxEvtHandler* toRemove) +{ + wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker); + + if (m_handlersWithPendingEvents.Index(toRemove) != wxNOT_FOUND) { - // iterate until the list becomes empty: the handlers remove themselves - // from it when they don't have any more pending events - wxList::compatibility_iterator node = wxPendingEvents->GetFirst(); - while (node) - { - // In ProcessPendingEvents(), new handlers might be add - // and we can safely leave the critical section here. - wxLEAVE_CRIT_SECT( *wxPendingEventsLocker ); + m_handlersWithPendingEvents.Remove(toRemove); - wxEvtHandler *handler = (wxEvtHandler *)node->GetData(); - handler->ProcessPendingEvents(); + // check that the handler was present only once in the list + wxASSERT_MSG( m_handlersWithPendingEvents.Index(toRemove) == wxNOT_FOUND, + "Handler occurs twice in the m_handlersWithPendingEvents list!" ); + } + //else: it wasn't in this list at all, it's ok - wxENTER_CRIT_SECT( *wxPendingEventsLocker ); + if (m_handlersWithPendingDelayedEvents.Index(toRemove) != wxNOT_FOUND) + { + m_handlersWithPendingDelayedEvents.Remove(toRemove); - // restart as the iterators could have been invalidated - node = wxPendingEvents->GetFirst(); - } + // check that the handler was present only once in the list + wxASSERT_MSG( m_handlersWithPendingDelayedEvents.Index(toRemove) == wxNOT_FOUND, + "Handler occurs twice in m_handlersWithPendingDelayedEvents list!" ); } + //else: it wasn't in this list at all, it's ok - wxLEAVE_CRIT_SECT( *wxPendingEventsLocker ); + wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker); } -void wxAppConsoleBase::WakeUpIdle() +void wxAppConsoleBase::AppendPendingEventHandler(wxEvtHandler* toAppend) { - if ( m_mainLoop ) - m_mainLoop->WakeUp(); + wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker); + + if ( m_handlersWithPendingEvents.Index(toAppend) == wxNOT_FOUND ) + m_handlersWithPendingEvents.Add(toAppend); + + wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker); } -bool wxAppConsoleBase::ProcessIdle() +bool wxAppConsoleBase::HasPendingEvents() const { - wxIdleEvent event; + wxENTER_CRIT_SECT(const_cast(this)->m_handlersWithPendingEventsLocker); + + bool has = !m_handlersWithPendingEvents.IsEmpty(); + + wxLEAVE_CRIT_SECT(const_cast(this)->m_handlersWithPendingEventsLocker); - event.SetEventObject(this); - ProcessEvent(event); - return event.MoreRequested(); + return has; } -int wxAppConsoleBase::FilterEvent(wxEvent& WXUNUSED(event)) +void wxAppConsoleBase::SuspendProcessingOfPendingEvents() { - // process the events normally by default - return -1; + wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker); + // entering the critical section locks blocks calls to ProcessPendingEvents() +} + +void wxAppConsoleBase::ResumeProcessingOfPendingEvents() +{ + wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker); +} + +void wxAppConsoleBase::ProcessPendingEvents() +{ + wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker); + + wxCHECK_RET( m_handlersWithPendingDelayedEvents.IsEmpty(), + "this helper list should be empty" ); + + // iterate until the list becomes empty: the handlers remove themselves + // from it when they don't have any more pending events + while (!m_handlersWithPendingEvents.IsEmpty()) + { + // In ProcessPendingEvents(), new handlers might be added + // and we can safely leave the critical section here. + wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker); + + // NOTE: we always call ProcessPendingEvents() on the first event handler + // with pending events because handlers auto-remove themselves + // from this list (see RemovePendingEventHandler) if they have no + // more pending events. + m_handlersWithPendingEvents[0]->ProcessPendingEvents(); + + wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker); + } + + // now the wxHandlersWithPendingEvents is surely empty; however some event + // handlers may have moved themselves into wxHandlersWithPendingDelayedEvents + // because of a selective wxYield call in progress. + // Now we need to move them back to wxHandlersWithPendingEvents so the next + // call to this function has the chance of processing them: + if (!m_handlersWithPendingDelayedEvents.IsEmpty()) + { + WX_APPEND_ARRAY(m_handlersWithPendingEvents, m_handlersWithPendingDelayedEvents); + m_handlersWithPendingDelayedEvents.Clear(); + } + + wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker); } // ---------------------------------------------------------------------------- @@ -421,6 +477,20 @@ wxAppConsoleBase::HandleEvent(wxEvtHandler *handler, (handler->*func)(event); } +void wxAppConsoleBase::CallEventHandler(wxEvtHandler *handler, + wxEventFunctor& functor, + wxEvent& event) const +{ + // If the functor holds a method then, for backward compatibility, call + // HandleEvent(): + wxEventFunction eventFunction = functor.GetMethod(); + + if ( eventFunction ) + HandleEvent(handler, eventFunction, event); + else + functor(handler, event); +} + void wxAppConsoleBase::OnUnhandledException() { #ifdef __WXDEBUG__ @@ -563,7 +633,6 @@ bool wxAppConsoleBase::CheckBuildOptions(const char *optionsSignature, // normally wxLogFatalError doesn't return return false; } -#undef wxCMP return true; } @@ -677,12 +746,16 @@ void wxAppTraitsBase::MutexGuiLeave() void WXDLLIMPEXP_BASE wxMutexGuiEnter() { - wxAppConsoleBase::GetInstance()->GetTraits()->MutexGuiEnter(); + wxAppTraits * const traits = wxAppConsoleBase::GetTraitsIfExists(); + if ( traits ) + traits->MutexGuiEnter(); } void WXDLLIMPEXP_BASE wxMutexGuiLeave() { - wxAppConsoleBase::GetInstance()->GetTraits()->MutexGuiLeave(); + wxAppTraits * const traits = wxAppConsoleBase::GetTraitsIfExists(); + if ( traits ) + traits->MutexGuiLeave(); } #endif // wxUSE_THREADS