add wxAppConsoleBase::DeletePendingEvents and wxEvtHandler::DeletePendingEvents.
Fix wxAppConsoleBase::Suspend/ResumeProcessingOfPendingEvents: locking the mutex does not prevent wxAppConsoleBase::ProcessPendingEvents from running if the mutex was locked from the main thread! git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@59433 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -313,6 +313,9 @@ public:
|
|||||||
//to the list of the handlers with _delayed_ pending events
|
//to the list of the handlers with _delayed_ pending events
|
||||||
void DelayPendingEventHandler(wxEvtHandler* toDelay);
|
void DelayPendingEventHandler(wxEvtHandler* toDelay);
|
||||||
|
|
||||||
|
// deletes the current pending events
|
||||||
|
void DeletePendingEvents();
|
||||||
|
|
||||||
|
|
||||||
// wxEventLoop redirections
|
// wxEventLoop redirections
|
||||||
// ------------------------
|
// ------------------------
|
||||||
@@ -420,11 +423,17 @@ protected:
|
|||||||
// been started yet or has already terminated)
|
// been started yet or has already terminated)
|
||||||
wxEventLoopBase *m_mainLoop;
|
wxEventLoopBase *m_mainLoop;
|
||||||
|
|
||||||
|
|
||||||
|
// pending events management vars:
|
||||||
|
|
||||||
// the array of the handlers with pending events which needs to be processed
|
// the array of the handlers with pending events which needs to be processed
|
||||||
// inside ProcessPendingEvents()
|
// inside ProcessPendingEvents()
|
||||||
wxEvtHandlerArray m_handlersWithPendingEvents;
|
wxEvtHandlerArray m_handlersWithPendingEvents;
|
||||||
|
|
||||||
// helper array used by ProcessPendingEvents()
|
// helper array used by ProcessPendingEvents() to store the event handlers
|
||||||
|
// which have pending events but of these events none can be processed right now
|
||||||
|
// (because of a call to wxEventLoop::YieldFor() which asked to selectively process
|
||||||
|
// pending events)
|
||||||
wxEvtHandlerArray m_handlersWithPendingDelayedEvents;
|
wxEvtHandlerArray m_handlersWithPendingDelayedEvents;
|
||||||
|
|
||||||
#if wxUSE_THREADS
|
#if wxUSE_THREADS
|
||||||
@@ -432,6 +441,9 @@ protected:
|
|||||||
wxCriticalSection m_handlersWithPendingEventsLocker;
|
wxCriticalSection m_handlersWithPendingEventsLocker;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// flag modified by Suspend/ResumeProcessingOfPendingEvents()
|
||||||
|
bool m_bDoPendingEventProcessing;
|
||||||
|
|
||||||
friend class WXDLLIMPEXP_FWD_BASE wxEvtHandler;
|
friend class WXDLLIMPEXP_FWD_BASE wxEvtHandler;
|
||||||
|
|
||||||
// the application object is a singleton anyhow, there is no sense in
|
// the application object is a singleton anyhow, there is no sense in
|
||||||
|
@@ -2864,7 +2864,6 @@ public:
|
|||||||
// Event queuing and processing
|
// Event queuing and processing
|
||||||
// ----------------------------
|
// ----------------------------
|
||||||
|
|
||||||
|
|
||||||
// Process an event right now: this can only be called from the main
|
// Process an event right now: this can only be called from the main
|
||||||
// thread, use QueueEvent() for scheduling the events for
|
// thread, use QueueEvent() for scheduling the events for
|
||||||
// processing from other threads.
|
// processing from other threads.
|
||||||
@@ -2900,9 +2899,11 @@ public:
|
|||||||
void ProcessPendingEvents();
|
void ProcessPendingEvents();
|
||||||
// NOTE: uses ProcessEvent()
|
// NOTE: uses ProcessEvent()
|
||||||
|
|
||||||
|
void DeletePendingEvents();
|
||||||
|
|
||||||
#if wxUSE_THREADS
|
#if wxUSE_THREADS
|
||||||
bool ProcessThreadEvent(const wxEvent& event);
|
bool ProcessThreadEvent(const wxEvent& event);
|
||||||
// NOTE: uses AddPendingEvent()
|
// NOTE: uses AddPendingEvent(); call only from secondary threads
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@@ -125,15 +125,35 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
Process all pending events; it is necessary to call this function to
|
Process all pending events; it is necessary to call this function to
|
||||||
process posted events.
|
process events posted with wxEvtHandler::QueueEvent or wxEvtHandler::AddPendingEvent.
|
||||||
|
|
||||||
This happens during each event loop iteration in GUI mode but
|
This happens during each event loop iteration (see wxEventLoopBase) in GUI mode but
|
||||||
it may be also called directly.
|
it may be also called directly.
|
||||||
|
|
||||||
|
Note that this function does not only process the pending events for the wxApp object
|
||||||
|
itself (which derives from wxEvtHandler) but also the pending events for @e any
|
||||||
|
event handler of this application.
|
||||||
|
|
||||||
|
This function will immediately return and do nothing if SuspendProcessingOfPendingEvents()
|
||||||
|
was called.
|
||||||
*/
|
*/
|
||||||
virtual void ProcessPendingEvents();
|
virtual void ProcessPendingEvents();
|
||||||
|
|
||||||
|
/**
|
||||||
|
Deletes the pending events of all wxEvtHandlers of this application.
|
||||||
|
|
||||||
|
See wxEvtHandler::DeletePendingEvents() for warnings about deleting the pending
|
||||||
|
events.
|
||||||
|
*/
|
||||||
|
void DeletePendingEvents();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns @true if there are pending events on the internal pending event list.
|
Returns @true if there are pending events on the internal pending event list.
|
||||||
|
|
||||||
|
Whenever wxEvtHandler::QueueEvent or wxEvtHandler::AddPendingEvent() are
|
||||||
|
called (not only for wxApp itself, but for any event handler of the application!),
|
||||||
|
the internal wxApp's list of handlers with pending events is updated and this
|
||||||
|
function will return true.
|
||||||
*/
|
*/
|
||||||
bool HasPendingEvents() const;
|
bool HasPendingEvents() const;
|
||||||
|
|
||||||
|
@@ -534,6 +534,31 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool SafelyProcessEvent(wxEvent& event);
|
bool SafelyProcessEvent(wxEvent& event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Processes the pending events previously queued using QueueEvent() or
|
||||||
|
AddPendingEvent(); you must call this function only if you are sure
|
||||||
|
there are pending events for this handler, otherwise a @c wxCHECK
|
||||||
|
will fail.
|
||||||
|
|
||||||
|
The real processing still happens in ProcessEvent() which is called by this
|
||||||
|
function.
|
||||||
|
|
||||||
|
Note that this function needs a valid application object (see
|
||||||
|
wxAppConsole::GetInstance()) because wxApp holds the list of the event
|
||||||
|
handlers with pending events and this function manipulates that list.
|
||||||
|
*/
|
||||||
|
void ProcessPendingEvents();
|
||||||
|
|
||||||
|
/**
|
||||||
|
Deletes all events queued on this event handler using QueueEvent() or
|
||||||
|
AddPendingEvent().
|
||||||
|
|
||||||
|
Use with care because the events which are deleted are (obviously) not
|
||||||
|
processed and this may have unwanted consequences (e.g. user actions events
|
||||||
|
will be lost).
|
||||||
|
*/
|
||||||
|
void DeletePendingEvents();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Searches the event table, executing an event handler function if an appropriate
|
Searches the event table, executing an event handler function if an appropriate
|
||||||
one is found.
|
one is found.
|
||||||
@@ -556,6 +581,9 @@ public:
|
|||||||
If a suitable function is called but calls wxEvent::Skip, this
|
If a suitable function is called but calls wxEvent::Skip, this
|
||||||
function will fail, and searching will continue.
|
function will fail, and searching will continue.
|
||||||
|
|
||||||
|
@todo this function in the header is listed as an "implementation only" function;
|
||||||
|
are we sure we want to document it?
|
||||||
|
|
||||||
@see ProcessEvent()
|
@see ProcessEvent()
|
||||||
*/
|
*/
|
||||||
virtual bool SearchEventTable(wxEventTable& table,
|
virtual bool SearchEventTable(wxEventTable& table,
|
||||||
|
@@ -132,6 +132,7 @@ wxAppConsoleBase::wxAppConsoleBase()
|
|||||||
{
|
{
|
||||||
m_traits = NULL;
|
m_traits = NULL;
|
||||||
m_mainLoop = NULL;
|
m_mainLoop = NULL;
|
||||||
|
m_bDoPendingEventProcessing = true;
|
||||||
|
|
||||||
ms_appInstance = static_cast<wxAppConsole *>(this);
|
ms_appInstance = static_cast<wxAppConsole *>(this);
|
||||||
|
|
||||||
@@ -415,17 +416,19 @@ bool wxAppConsoleBase::HasPendingEvents() const
|
|||||||
|
|
||||||
void wxAppConsoleBase::SuspendProcessingOfPendingEvents()
|
void wxAppConsoleBase::SuspendProcessingOfPendingEvents()
|
||||||
{
|
{
|
||||||
wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
m_bDoPendingEventProcessing = false;
|
||||||
// entering the critical section locks blocks calls to ProcessPendingEvents()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxAppConsoleBase::ResumeProcessingOfPendingEvents()
|
void wxAppConsoleBase::ResumeProcessingOfPendingEvents()
|
||||||
{
|
{
|
||||||
wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
m_bDoPendingEventProcessing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxAppConsoleBase::ProcessPendingEvents()
|
void wxAppConsoleBase::ProcessPendingEvents()
|
||||||
{
|
{
|
||||||
|
if (!m_bDoPendingEventProcessing)
|
||||||
|
return;
|
||||||
|
|
||||||
wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
||||||
|
|
||||||
wxCHECK_RET( m_handlersWithPendingDelayedEvents.IsEmpty(),
|
wxCHECK_RET( m_handlersWithPendingDelayedEvents.IsEmpty(),
|
||||||
@@ -462,6 +465,21 @@ void wxAppConsoleBase::ProcessPendingEvents()
|
|||||||
wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxAppConsoleBase::DeletePendingEvents()
|
||||||
|
{
|
||||||
|
wxENTER_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
||||||
|
|
||||||
|
wxCHECK_RET( m_handlersWithPendingDelayedEvents.IsEmpty(),
|
||||||
|
"this helper list should be empty" );
|
||||||
|
|
||||||
|
for (unsigned int i=0; i<m_handlersWithPendingEvents.GetCount(); i++)
|
||||||
|
m_handlersWithPendingEvents[i]->DeletePendingEvents();
|
||||||
|
|
||||||
|
m_handlersWithPendingEvents.Clear();
|
||||||
|
|
||||||
|
wxLEAVE_CRIT_SECT(m_handlersWithPendingEventsLocker);
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// exception handling
|
// exception handling
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@@ -1079,14 +1079,12 @@ wxEvtHandler::~wxEvtHandler()
|
|||||||
delete m_dynamicEvents;
|
delete m_dynamicEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_pendingEvents)
|
|
||||||
m_pendingEvents->DeleteContents(true);
|
|
||||||
delete m_pendingEvents;
|
|
||||||
|
|
||||||
// Remove us from the list of the pending events if necessary.
|
// Remove us from the list of the pending events if necessary.
|
||||||
if (wxTheApp)
|
if (wxTheApp)
|
||||||
wxTheApp->RemovePendingEventHandler(this);
|
wxTheApp->RemovePendingEventHandler(this);
|
||||||
|
|
||||||
|
DeletePendingEvents();
|
||||||
|
|
||||||
// we only delete object data, not untyped
|
// we only delete object data, not untyped
|
||||||
if ( m_clientDataType == wxClientData_Object )
|
if ( m_clientDataType == wxClientData_Object )
|
||||||
delete m_clientObject;
|
delete m_clientObject;
|
||||||
@@ -1169,6 +1167,13 @@ void wxEvtHandler::QueueEvent(wxEvent *event)
|
|||||||
wxWakeUpIdle();
|
wxWakeUpIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxEvtHandler::DeletePendingEvents()
|
||||||
|
{
|
||||||
|
if (m_pendingEvents)
|
||||||
|
m_pendingEvents->DeleteContents(true);
|
||||||
|
wxDELETE(m_pendingEvents);
|
||||||
|
}
|
||||||
|
|
||||||
void wxEvtHandler::ProcessPendingEvents()
|
void wxEvtHandler::ProcessPendingEvents()
|
||||||
{
|
{
|
||||||
if (!wxTheApp)
|
if (!wxTheApp)
|
||||||
|
Reference in New Issue
Block a user