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
This commit is contained in:
@@ -277,14 +277,46 @@ public:
|
||||
#endif // wxUSE_EXCEPTIONS
|
||||
|
||||
|
||||
// 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 void SuspendProcessingOfPendingEvents();
|
||||
virtual void ResumeProcessingOfPendingEvents();
|
||||
virtual void ProcessPendingEvents();
|
||||
bool HasPendingEvents() const;
|
||||
|
||||
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
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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.
|
||||
|
@@ -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
|
||||
{
|
||||
|
@@ -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
|
||||
*/
|
||||
|
@@ -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<wxAppConsoleBase*>(this)->m_handlersWithPendingEventsLocker);
|
||||
|
||||
bool has = !m_handlersWithPendingEvents.IsEmpty();
|
||||
|
||||
wxLEAVE_CRIT_SECT(const_cast<wxAppConsoleBase*>(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
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@@ -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,11 +1240,8 @@ void wxEvtHandler::ProcessPendingEvents()
|
||||
// of this object any more
|
||||
}
|
||||
|
||||
/*
|
||||
* Event table stuff
|
||||
*/
|
||||
/* static */ bool
|
||||
wxEvtHandler::ProcessEventIfMatchesId(const wxEventTableEntryBase& entry,
|
||||
/* static */
|
||||
bool wxEvtHandler::ProcessEventIfMatchesId(const wxEventTableEntryBase& entry,
|
||||
wxEvtHandler *handler,
|
||||
wxEvent& event)
|
||||
{
|
||||
@@ -1412,7 +1414,6 @@ bool wxEvtHandler::SafelyProcessEvent(wxEvent& event)
|
||||
#endif // wxUSE_EXCEPTIONS
|
||||
}
|
||||
|
||||
|
||||
bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event)
|
||||
{
|
||||
const wxEventType eventType = event.GetEventType();
|
||||
|
@@ -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<wxEventLoopBase*>(this)->m_handlersWithPendingEventsLocker);
|
||||
|
||||
bool has = !m_handlersWithPendingEvents.IsEmpty();
|
||||
|
||||
wxLEAVE_CRIT_SECT(const_cast<wxEventLoopBase*>(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();
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user