From 8e40ed8535894eb47af679ad2b08e777c3605dd0 Mon Sep 17 00:00:00 2001 From: Francesco Montorsi Date: Mon, 2 Mar 2009 20:45:22 +0000 Subject: [PATCH] move pending event processing back to wxApp (these methods were moved into wxEventLoopBase during YieldFor() refactoring - see #10320): we need to be able to queue events even when there's no event loop running (e.g. wxApp::OnInit) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@59284 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/app.h | 54 +++++++++++++-- include/wx/evtloop.h | 45 +----------- interface/wx/app.h | 39 +++++++++++ interface/wx/event.h | 2 +- interface/wx/evtloop.h | 35 ---------- src/common/appbase.cpp | 139 ++++++++++++++++++++++++++++++-------- src/common/event.cpp | 85 +++++++++++------------ src/common/evtloopcmn.cpp | 118 ++------------------------------ 8 files changed, 250 insertions(+), 267 deletions(-) diff --git a/include/wx/app.h b/include/wx/app.h index 10a99bf981..1a9a083f5e 100644 --- a/include/wx/app.h +++ b/include/wx/app.h @@ -277,14 +277,46 @@ public: #endif // wxUSE_EXCEPTIONS - // wxEventLoop redirections - // ------------------------ - - virtual void SuspendProcessingOfPendingEvents(); - virtual void ResumeProcessingOfPendingEvents(); + // pending events + // -------------- + + // IMPORTANT: all these methods conceptually belong to wxEventLoopBase + // but for many reasons we need to allow queuing of events + // even when there's no event loop (e.g. in wxApp::OnInit); + // this feature is used e.g. to queue events on secondary threads + // or in wxPython to use wx.CallAfter before the GUI is initialized + + // process all events in the m_handlersWithPendingEvents list -- it is necessary + // to call this function to process posted events. This happens during each + // event loop iteration in GUI mode but if there is no main loop, it may be + // also called directly. virtual void ProcessPendingEvents(); + + // check if there are pending events on global pending event list bool HasPendingEvents() const; + // temporary suspends processing of the pending events + void SuspendProcessingOfPendingEvents(); + + // resume processing of the pending events previously stopped because of a + // call to SuspendProcessingOfPendingEvents() + void ResumeProcessingOfPendingEvents(); + + // called by ~wxEvtHandler to (eventually) remove the handler from the list of + // the handlers with pending events + void RemovePendingEventHandler(wxEvtHandler* toRemove); + + // adds an event handler to the list of the handlers with pending events + void AppendPendingEventHandler(wxEvtHandler* toAppend); + + // moves the event handler from the list of the handlers with pending events + //to the list of the handlers with _delayed_ pending events + void DelayPendingEventHandler(wxEvtHandler* toDelay); + + + // wxEventLoop redirections + // ------------------------ + virtual bool Pending(); virtual bool Dispatch(); @@ -388,6 +420,18 @@ protected: // been started yet or has already terminated) wxEventLoopBase *m_mainLoop; + // the array of the handlers with pending events which needs to be processed + // inside ProcessPendingEvents() + wxEvtHandlerArray m_handlersWithPendingEvents; + + // helper array used by ProcessPendingEvents() + wxEvtHandlerArray m_handlersWithPendingDelayedEvents; + +#if wxUSE_THREADS + // this critical section protects both the lists above + wxCriticalSection m_handlersWithPendingEventsLocker; +#endif + friend class WXDLLIMPEXP_FWD_BASE wxEvtHandler; // the application object is a singleton anyhow, there is no sense in diff --git a/include/wx/evtloop.h b/include/wx/evtloop.h index df144fb97a..8bea93090a 100644 --- a/include/wx/evtloop.h +++ b/include/wx/evtloop.h @@ -96,37 +96,6 @@ public: virtual void WakeUp() = 0; - // pending events - // -------------- - - // process all events in the wxHandlersWithPendingEvents list -- it is necessary - // to call this function to process posted events. This happens during each - // event loop iteration in GUI mode but if there is no main loop, it may be - // also called directly. - virtual void ProcessPendingEvents(); - - // check if there are pending events on global pending event list - bool HasPendingEvents() const; - - // temporary suspends processing of the pending events - void SuspendProcessingOfPendingEvents(); - - // resume processing of the pending events previously stopped because of a - // call to SuspendProcessingOfPendingEvents() - void ResumeProcessingOfPendingEvents(); - - // called by ~wxEvtHandler to (eventually) remove the handler from the list of - // the handlers with pending events - void RemovePendingEventHandler(wxEvtHandler* toRemove); - - // adds an event handler to the list of the handlers with pending events - void AppendPendingEventHandler(wxEvtHandler* toAppend); - - // moves the event handler from the list of the handlers with pending events - //to the list of the handlers with _delayed_ pending events - void DelayPendingEventHandler(wxEvtHandler* toDelay); - - // idle handling // ------------- @@ -188,19 +157,7 @@ protected: // the pointer to currently active loop static wxEventLoopBase *ms_activeLoop; - // the array of the handlers with pending events which needs to be processed - // inside ProcessPendingEvents() - wxEvtHandlerArray m_handlersWithPendingEvents; - - // helper array used by ProcessPendingEvents() - wxEvtHandlerArray m_handlersWithPendingDelayedEvents; - -#if wxUSE_THREADS - // this critical section protects both the lists above - wxCriticalSection m_handlersWithPendingEventsLocker; -#endif - - // Yield() helpers: + // YieldFor() helpers: bool m_isInsideYield; long m_eventsToProcessInsideYield; diff --git a/interface/wx/app.h b/interface/wx/app.h index 4652096e3f..9d358c7473 100644 --- a/interface/wx/app.h +++ b/interface/wx/app.h @@ -114,6 +114,45 @@ public: //@} + /** + @name Pending events + + Pending events are handled by wxAppConsole rather than wxEventLoopBase + to allow queuing of events even when there's no event loop + (e.g. in wxAppConsole::OnInit). + */ + //@{ + + /** + Process all pending events; it is necessary to call this function to + process posted events. + + This happens during each event loop iteration in GUI mode but + it may be also called directly. + */ + virtual void ProcessPendingEvents(); + + /** + Returns @true if there are pending events on the internal pending event list. + */ + bool HasPendingEvents() const; + + /** + Temporary suspends processing of the pending events. + + @see ResumeProcessingOfPendingEvents() + */ + void SuspendProcessingOfPendingEvents(); + + /** + Resume processing of the pending events previously stopped because of a + call to SuspendProcessingOfPendingEvents(). + */ + void ResumeProcessingOfPendingEvents(); + + //@} + + /** Allows external code to modify global ::wxTheApp, but you should really know what you're doing if you call it. diff --git a/interface/wx/event.h b/interface/wx/event.h index d0ea624e1f..2e80f9c739 100644 --- a/interface/wx/event.h +++ b/interface/wx/event.h @@ -333,7 +333,7 @@ public: @library{wxbase} @category{events} - @see @ref overview_events_processing + @see @ref overview_events_processing, wxEventBlocker, wxEventLoopBase */ class wxEvtHandler : public wxObject { diff --git a/interface/wx/evtloop.h b/interface/wx/evtloop.h index 885ce45862..4322ac08d0 100644 --- a/interface/wx/evtloop.h +++ b/interface/wx/evtloop.h @@ -146,41 +146,6 @@ public: //@} - /** - @name Pending events - */ - //@{ - - /** - Process all pending events; it is necessary to call this function to - process posted events. - - This happens during each event loop iteration in GUI mode but - it may be also called directly. - */ - virtual void ProcessPendingEvents(); - - /** - Returns @true if there are pending events on the internal pending event list. - */ - bool HasPendingEvents() const; - - /** - Temporary suspends processing of the pending events. - - @see ResumeProcessingOfPendingEvents() - */ - void SuspendProcessingOfPendingEvents(); - - /** - Resume processing of the pending events previously stopped because of a - call to SuspendProcessingOfPendingEvents(). - */ - void ResumeProcessingOfPendingEvents(); - - //@} - - /** @name Idle handling */ diff --git a/src/common/appbase.cpp b/src/common/appbase.cpp index 81dacee807..a78e93d1d4 100644 --- a/src/common/appbase.cpp +++ b/src/common/appbase.cpp @@ -313,34 +313,6 @@ bool wxAppConsoleBase::Dispatch() return loop && loop->Dispatch(); } -bool wxAppConsoleBase::HasPendingEvents() const -{ - wxEventLoopBase * const loop = wxEventLoopBase::GetActive(); - - return loop && loop->HasPendingEvents(); -} - -void wxAppConsoleBase::SuspendProcessingOfPendingEvents() -{ - wxEventLoopBase * const loop = wxEventLoopBase::GetActive(); - - if (loop) loop->SuspendProcessingOfPendingEvents(); -} - -void wxAppConsoleBase::ResumeProcessingOfPendingEvents() -{ - wxEventLoopBase * const loop = wxEventLoopBase::GetActive(); - - if (loop) loop->ResumeProcessingOfPendingEvents(); -} - -void wxAppConsoleBase::ProcessPendingEvents() -{ - wxEventLoopBase * const loop = wxEventLoopBase::GetActive(); - - if (loop) loop->ProcessPendingEvents(); -} - bool wxAppConsoleBase::Yield(bool onlyIfNeeded) { wxEventLoopBase * const loop = wxEventLoopBase::GetActive(); @@ -379,6 +351,117 @@ int wxAppConsoleBase::FilterEvent(wxEvent& WXUNUSED(event)) 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); + + if (m_handlersWithPendingDelayedEvents.Index(toDelay) == wxNOT_FOUND) + m_handlersWithPendingDelayedEvents.Add(toDelay); + + wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker); +} + +void wxAppConsoleBase::RemovePendingEventHandler(wxEvtHandler* toRemove) +{ + wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker); + + if (m_handlersWithPendingEvents.Index(toRemove) != wxNOT_FOUND) + { + m_handlersWithPendingEvents.Remove(toRemove); + + // 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 + + if (m_handlersWithPendingDelayedEvents.Index(toRemove) != wxNOT_FOUND) + { + m_handlersWithPendingDelayedEvents.Remove(toRemove); + + // 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(m_handlersWithPendingEventsLocker); +} + +void wxAppConsoleBase::AppendPendingEventHandler(wxEvtHandler* toAppend) +{ + wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker); + + if ( m_handlersWithPendingEvents.Index(toAppend) == wxNOT_FOUND ) + m_handlersWithPendingEvents.Add(toAppend); + + wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker); +} + +bool wxAppConsoleBase::HasPendingEvents() const +{ + wxENTER_CRIT_SECT(const_cast(this)->m_handlersWithPendingEventsLocker); + + bool has = !m_handlersWithPendingEvents.IsEmpty(); + + wxLEAVE_CRIT_SECT(const_cast(this)->m_handlersWithPendingEventsLocker); + + return has; +} + +void wxAppConsoleBase::SuspendProcessingOfPendingEvents() +{ + 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); +} + // ---------------------------------------------------------------------------- // exception handling // ---------------------------------------------------------------------------- diff --git a/src/common/event.cpp b/src/common/event.cpp index af8b2ac1b2..7118b7dbd9 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -402,10 +402,9 @@ wxEvent& wxEvent::operator=(const wxEvent& src) #if wxUSE_GUI -/* - * Command events - * - */ +// ---------------------------------------------------------------------------- +// wxCommandEvent +// ---------------------------------------------------------------------------- #ifdef __VISUALC__ // 'this' : used in base member initializer list (for m_commandString) @@ -447,9 +446,9 @@ wxString wxCommandEvent::GetString() const } } -/* - * UI update events - */ +// ---------------------------------------------------------------------------- +// wxUpdateUIEvent +// ---------------------------------------------------------------------------- #if wxUSE_LONGLONG wxLongLong wxUpdateUIEvent::sm_lastUpdate = 0; @@ -506,9 +505,9 @@ void wxUpdateUIEvent::ResetUpdateTime() #endif } -/* - * Scroll events - */ +// ---------------------------------------------------------------------------- +// wxScrollEvent +// ---------------------------------------------------------------------------- wxScrollEvent::wxScrollEvent(wxEventType commandType, int id, @@ -520,9 +519,9 @@ wxScrollEvent::wxScrollEvent(wxEventType commandType, m_commandInt = pos; } -/* - * ScrollWin events - */ +// ---------------------------------------------------------------------------- +// wxScrollWinEvent +// ---------------------------------------------------------------------------- wxScrollWinEvent::wxScrollWinEvent(wxEventType commandType, int pos, @@ -533,10 +532,9 @@ wxScrollWinEvent::wxScrollWinEvent(wxEventType commandType, m_commandInt = pos; } -/* - * Mouse events - * - */ +// ---------------------------------------------------------------------------- +// wxMouseEvent +// ---------------------------------------------------------------------------- wxMouseEvent::wxMouseEvent(wxEventType commandType) { @@ -751,11 +749,9 @@ wxPoint wxMouseEvent::GetLogicalPosition(const wxDC& dc) const return pt; } - -/* - * Keyboard event - * - */ +// ---------------------------------------------------------------------------- +// wxKeyEvent +// ---------------------------------------------------------------------------- wxKeyEvent::wxKeyEvent(wxEventType type) { @@ -782,18 +778,30 @@ wxKeyEvent::wxKeyEvent(const wxKeyEvent& evt) #endif } +// ---------------------------------------------------------------------------- +// wxWindowCreateEvent +// ---------------------------------------------------------------------------- + wxWindowCreateEvent::wxWindowCreateEvent(wxWindow *win) { SetEventType(wxEVT_CREATE); SetEventObject(win); } +// ---------------------------------------------------------------------------- +// wxWindowDestroyEvent +// ---------------------------------------------------------------------------- + wxWindowDestroyEvent::wxWindowDestroyEvent(wxWindow *win) { SetEventType(wxEVT_DESTROY); SetEventObject(win); } +// ---------------------------------------------------------------------------- +// wxChildFocusEvent +// ---------------------------------------------------------------------------- + wxChildFocusEvent::wxChildFocusEvent(wxWindow *win) : wxCommandEvent(wxEVT_CHILD_FOCUS) { @@ -1076,9 +1084,8 @@ wxEvtHandler::~wxEvtHandler() delete m_pendingEvents; // Remove us from the list of the pending events if necessary. - wxEventLoopBase *loop = wxEventLoopBase::GetActive(); - if (loop) - loop->RemovePendingEventHandler(this); + if (wxTheApp) + wxTheApp->RemovePendingEventHandler(this); // we only delete object data, not untyped if ( m_clientDataType == wxClientData_Object ) @@ -1124,12 +1131,11 @@ void wxEvtHandler::QueueEvent(wxEvent *event) { wxCHECK_RET( event, "NULL event can't be posted" ); - wxEventLoopBase* loop = wxEventLoopBase::GetActive(); - if (!loop) + if (!wxTheApp) { // 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!"); + wxLogDebug("No application object! Cannot queue this event!"); // anyway delete the given event to avoid memory leaks delete event; @@ -1148,7 +1154,7 @@ void wxEvtHandler::QueueEvent(wxEvent *event) // 2) Add this event handler to list of event handlers that // have pending events. - loop->AppendPendingEventHandler(this); + wxTheApp->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 @@ -1165,12 +1171,11 @@ void wxEvtHandler::QueueEvent(wxEvent *event) void wxEvtHandler::ProcessPendingEvents() { - wxEventLoopBase* loop = wxEventLoopBase::GetActive(); - if (!loop) + if (!wxTheApp) { // 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!"); + wxLogDebug("No application object! Cannot process pending events!"); return; } @@ -1201,7 +1206,7 @@ void wxEvtHandler::ProcessPendingEvents() if (!node) { // all our events are NOT processable now... signal this: - loop->DelayPendingEventHandler(this); + wxTheApp->DelayPendingEventHandler(this); // see the comment at the beginning of evtloop.h header for the // logic behind YieldFor() and behind DelayPendingEventHandler() @@ -1223,7 +1228,7 @@ void wxEvtHandler::ProcessPendingEvents() { // if there are no more pending events left, we don't need to // stay in this list - loop->RemovePendingEventHandler(this); + wxTheApp->RemovePendingEventHandler(this); } wxLEAVE_CRIT_SECT( m_pendingEventsLock ); @@ -1235,13 +1240,10 @@ void wxEvtHandler::ProcessPendingEvents() // of this object any more } -/* - * Event table stuff - */ -/* static */ bool -wxEvtHandler::ProcessEventIfMatchesId(const wxEventTableEntryBase& entry, - wxEvtHandler *handler, - wxEvent& event) +/* static */ +bool wxEvtHandler::ProcessEventIfMatchesId(const wxEventTableEntryBase& entry, + wxEvtHandler *handler, + wxEvent& event) { int tableId1 = entry.m_id, tableId2 = entry.m_lastId; @@ -1412,7 +1414,6 @@ bool wxEvtHandler::SafelyProcessEvent(wxEvent& event) #endif // wxUSE_EXCEPTIONS } - bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event) { const wxEventType eventType = event.GetEventType(); diff --git a/src/common/evtloopcmn.cpp b/src/common/evtloopcmn.cpp index 863946f59d..15813725a8 100644 --- a/src/common/evtloopcmn.cpp +++ b/src/common/evtloopcmn.cpp @@ -56,116 +56,6 @@ void wxEventLoopBase::OnExit() wxTheApp->OnEventLoopExit(this); } -void wxEventLoopBase::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); - - if (m_handlersWithPendingDelayedEvents.Index(toDelay) == wxNOT_FOUND) - m_handlersWithPendingDelayedEvents.Add(toDelay); - - wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker); -} - -void wxEventLoopBase::RemovePendingEventHandler(wxEvtHandler* toRemove) -{ - wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker); - - if (m_handlersWithPendingEvents.Index(toRemove) != wxNOT_FOUND) - { - m_handlersWithPendingEvents.Remove(toRemove); - - // 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 - - if (m_handlersWithPendingDelayedEvents.Index(toRemove) != wxNOT_FOUND) - { - m_handlersWithPendingDelayedEvents.Remove(toRemove); - - // 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(m_handlersWithPendingEventsLocker); -} - -void wxEventLoopBase::AppendPendingEventHandler(wxEvtHandler* toAppend) -{ - wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker); - - if ( m_handlersWithPendingEvents.Index(toAppend) == wxNOT_FOUND ) - m_handlersWithPendingEvents.Add(toAppend); - - wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker); -} - -bool wxEventLoopBase::HasPendingEvents() const -{ - wxENTER_CRIT_SECT(const_cast(this)->m_handlersWithPendingEventsLocker); - - bool has = !m_handlersWithPendingEvents.IsEmpty(); - - wxLEAVE_CRIT_SECT(const_cast(this)->m_handlersWithPendingEventsLocker); - - return has; -} - -void wxEventLoopBase::SuspendProcessingOfPendingEvents() -{ - wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker); -} - -void wxEventLoopBase::ResumeProcessingOfPendingEvents() -{ - wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker); -} - -void wxEventLoopBase::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); -} - void wxEventLoopBase::WakeUpIdle() { WakeUp(); @@ -173,13 +63,17 @@ void wxEventLoopBase::WakeUpIdle() bool wxEventLoopBase::ProcessIdle() { + if (!wxTheApp) + return false; + // process pending wx events before sending idle events - ProcessPendingEvents(); + wxTheApp->ProcessPendingEvents(); + // synthetize an idle event and send it to wxApp wxIdleEvent event; - event.SetEventObject(wxTheApp); wxTheApp->ProcessEvent(event); + return event.MoreRequested(); } -- 2.45.2