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
|
#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
|
// wxEventLoop redirections
|
||||||
// ------------------------
|
// ------------------------
|
||||||
|
|
||||||
virtual void SuspendProcessingOfPendingEvents();
|
|
||||||
virtual void ResumeProcessingOfPendingEvents();
|
|
||||||
virtual void ProcessPendingEvents();
|
|
||||||
bool HasPendingEvents() const;
|
|
||||||
|
|
||||||
virtual bool Pending();
|
virtual bool Pending();
|
||||||
virtual bool Dispatch();
|
virtual bool Dispatch();
|
||||||
|
|
||||||
@@ -388,6 +420,18 @@ protected:
|
|||||||
// been started yet or has already terminated)
|
// been started yet or has already terminated)
|
||||||
wxEventLoopBase *m_mainLoop;
|
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;
|
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
|
||||||
|
@@ -96,37 +96,6 @@ public:
|
|||||||
virtual void WakeUp() = 0;
|
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
|
// idle handling
|
||||||
// -------------
|
// -------------
|
||||||
|
|
||||||
@@ -188,19 +157,7 @@ protected:
|
|||||||
// the pointer to currently active loop
|
// the pointer to currently active loop
|
||||||
static wxEventLoopBase *ms_activeLoop;
|
static wxEventLoopBase *ms_activeLoop;
|
||||||
|
|
||||||
// the array of the handlers with pending events which needs to be processed
|
// YieldFor() helpers:
|
||||||
// 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:
|
|
||||||
bool m_isInsideYield;
|
bool m_isInsideYield;
|
||||||
long m_eventsToProcessInsideYield;
|
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
|
Allows external code to modify global ::wxTheApp, but you should really
|
||||||
know what you're doing if you call it.
|
know what you're doing if you call it.
|
||||||
|
@@ -333,7 +333,7 @@ public:
|
|||||||
@library{wxbase}
|
@library{wxbase}
|
||||||
@category{events}
|
@category{events}
|
||||||
|
|
||||||
@see @ref overview_events_processing
|
@see @ref overview_events_processing, wxEventBlocker, wxEventLoopBase
|
||||||
*/
|
*/
|
||||||
class wxEvtHandler : public wxObject
|
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
|
@name Idle handling
|
||||||
*/
|
*/
|
||||||
|
@@ -313,34 +313,6 @@ bool wxAppConsoleBase::Dispatch()
|
|||||||
return loop && loop->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)
|
bool wxAppConsoleBase::Yield(bool onlyIfNeeded)
|
||||||
{
|
{
|
||||||
wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
|
wxEventLoopBase * const loop = wxEventLoopBase::GetActive();
|
||||||
@@ -379,6 +351,117 @@ int wxAppConsoleBase::FilterEvent(wxEvent& WXUNUSED(event))
|
|||||||
return -1;
|
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
|
// exception handling
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@@ -402,10 +402,9 @@ wxEvent& wxEvent::operator=(const wxEvent& src)
|
|||||||
|
|
||||||
#if wxUSE_GUI
|
#if wxUSE_GUI
|
||||||
|
|
||||||
/*
|
// ----------------------------------------------------------------------------
|
||||||
* Command events
|
// wxCommandEvent
|
||||||
*
|
// ----------------------------------------------------------------------------
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef __VISUALC__
|
#ifdef __VISUALC__
|
||||||
// 'this' : used in base member initializer list (for m_commandString)
|
// '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
|
#if wxUSE_LONGLONG
|
||||||
wxLongLong wxUpdateUIEvent::sm_lastUpdate = 0;
|
wxLongLong wxUpdateUIEvent::sm_lastUpdate = 0;
|
||||||
@@ -506,9 +505,9 @@ void wxUpdateUIEvent::ResetUpdateTime()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// ----------------------------------------------------------------------------
|
||||||
* Scroll events
|
// wxScrollEvent
|
||||||
*/
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
wxScrollEvent::wxScrollEvent(wxEventType commandType,
|
wxScrollEvent::wxScrollEvent(wxEventType commandType,
|
||||||
int id,
|
int id,
|
||||||
@@ -520,9 +519,9 @@ wxScrollEvent::wxScrollEvent(wxEventType commandType,
|
|||||||
m_commandInt = pos;
|
m_commandInt = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// ----------------------------------------------------------------------------
|
||||||
* ScrollWin events
|
// wxScrollWinEvent
|
||||||
*/
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
wxScrollWinEvent::wxScrollWinEvent(wxEventType commandType,
|
wxScrollWinEvent::wxScrollWinEvent(wxEventType commandType,
|
||||||
int pos,
|
int pos,
|
||||||
@@ -533,10 +532,9 @@ wxScrollWinEvent::wxScrollWinEvent(wxEventType commandType,
|
|||||||
m_commandInt = pos;
|
m_commandInt = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// ----------------------------------------------------------------------------
|
||||||
* Mouse events
|
// wxMouseEvent
|
||||||
*
|
// ----------------------------------------------------------------------------
|
||||||
*/
|
|
||||||
|
|
||||||
wxMouseEvent::wxMouseEvent(wxEventType commandType)
|
wxMouseEvent::wxMouseEvent(wxEventType commandType)
|
||||||
{
|
{
|
||||||
@@ -751,11 +749,9 @@ wxPoint wxMouseEvent::GetLogicalPosition(const wxDC& dc) const
|
|||||||
return pt;
|
return pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
/*
|
// wxKeyEvent
|
||||||
* Keyboard event
|
// ----------------------------------------------------------------------------
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
wxKeyEvent::wxKeyEvent(wxEventType type)
|
wxKeyEvent::wxKeyEvent(wxEventType type)
|
||||||
{
|
{
|
||||||
@@ -782,18 +778,30 @@ wxKeyEvent::wxKeyEvent(const wxKeyEvent& evt)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxWindowCreateEvent
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
wxWindowCreateEvent::wxWindowCreateEvent(wxWindow *win)
|
wxWindowCreateEvent::wxWindowCreateEvent(wxWindow *win)
|
||||||
{
|
{
|
||||||
SetEventType(wxEVT_CREATE);
|
SetEventType(wxEVT_CREATE);
|
||||||
SetEventObject(win);
|
SetEventObject(win);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxWindowDestroyEvent
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
wxWindowDestroyEvent::wxWindowDestroyEvent(wxWindow *win)
|
wxWindowDestroyEvent::wxWindowDestroyEvent(wxWindow *win)
|
||||||
{
|
{
|
||||||
SetEventType(wxEVT_DESTROY);
|
SetEventType(wxEVT_DESTROY);
|
||||||
SetEventObject(win);
|
SetEventObject(win);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxChildFocusEvent
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
wxChildFocusEvent::wxChildFocusEvent(wxWindow *win)
|
wxChildFocusEvent::wxChildFocusEvent(wxWindow *win)
|
||||||
: wxCommandEvent(wxEVT_CHILD_FOCUS)
|
: wxCommandEvent(wxEVT_CHILD_FOCUS)
|
||||||
{
|
{
|
||||||
@@ -1076,9 +1084,8 @@ wxEvtHandler::~wxEvtHandler()
|
|||||||
delete m_pendingEvents;
|
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.
|
||||||
wxEventLoopBase *loop = wxEventLoopBase::GetActive();
|
if (wxTheApp)
|
||||||
if (loop)
|
wxTheApp->RemovePendingEventHandler(this);
|
||||||
loop->RemovePendingEventHandler(this);
|
|
||||||
|
|
||||||
// we only delete object data, not untyped
|
// we only delete object data, not untyped
|
||||||
if ( m_clientDataType == wxClientData_Object )
|
if ( m_clientDataType == wxClientData_Object )
|
||||||
@@ -1124,12 +1131,11 @@ void wxEvtHandler::QueueEvent(wxEvent *event)
|
|||||||
{
|
{
|
||||||
wxCHECK_RET( event, "NULL event can't be posted" );
|
wxCHECK_RET( event, "NULL event can't be posted" );
|
||||||
|
|
||||||
wxEventLoopBase* loop = wxEventLoopBase::GetActive();
|
if (!wxTheApp)
|
||||||
if (!loop)
|
|
||||||
{
|
{
|
||||||
// we need an event loop which manages the list of event handlers with
|
// we need an event loop which manages the list of event handlers with
|
||||||
// pending events... cannot proceed without it!
|
// 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
|
// anyway delete the given event to avoid memory leaks
|
||||||
delete event;
|
delete event;
|
||||||
@@ -1148,7 +1154,7 @@ void wxEvtHandler::QueueEvent(wxEvent *event)
|
|||||||
// 2) Add this event handler to list of event handlers that
|
// 2) Add this event handler to list of event handlers that
|
||||||
// have pending events.
|
// have pending events.
|
||||||
|
|
||||||
loop->AppendPendingEventHandler(this);
|
wxTheApp->AppendPendingEventHandler(this);
|
||||||
|
|
||||||
// only release m_pendingEventsLock now because otherwise there is a race
|
// only release m_pendingEventsLock now because otherwise there is a race
|
||||||
// condition as described in the ticket #9093: we could process the event
|
// condition as described in the ticket #9093: we could process the event
|
||||||
@@ -1165,12 +1171,11 @@ void wxEvtHandler::QueueEvent(wxEvent *event)
|
|||||||
|
|
||||||
void wxEvtHandler::ProcessPendingEvents()
|
void wxEvtHandler::ProcessPendingEvents()
|
||||||
{
|
{
|
||||||
wxEventLoopBase* loop = wxEventLoopBase::GetActive();
|
if (!wxTheApp)
|
||||||
if (!loop)
|
|
||||||
{
|
{
|
||||||
// we need an event loop which manages the list of event handlers with
|
// we need an event loop which manages the list of event handlers with
|
||||||
// pending events... cannot proceed without it!
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1201,7 +1206,7 @@ void wxEvtHandler::ProcessPendingEvents()
|
|||||||
if (!node)
|
if (!node)
|
||||||
{
|
{
|
||||||
// all our events are NOT processable now... signal this:
|
// 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
|
// see the comment at the beginning of evtloop.h header for the
|
||||||
// logic behind YieldFor() and behind DelayPendingEventHandler()
|
// 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
|
// if there are no more pending events left, we don't need to
|
||||||
// stay in this list
|
// stay in this list
|
||||||
loop->RemovePendingEventHandler(this);
|
wxTheApp->RemovePendingEventHandler(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxLEAVE_CRIT_SECT( m_pendingEventsLock );
|
wxLEAVE_CRIT_SECT( m_pendingEventsLock );
|
||||||
@@ -1235,13 +1240,10 @@ void wxEvtHandler::ProcessPendingEvents()
|
|||||||
// of this object any more
|
// of this object any more
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* static */
|
||||||
* Event table stuff
|
bool wxEvtHandler::ProcessEventIfMatchesId(const wxEventTableEntryBase& entry,
|
||||||
*/
|
wxEvtHandler *handler,
|
||||||
/* static */ bool
|
wxEvent& event)
|
||||||
wxEvtHandler::ProcessEventIfMatchesId(const wxEventTableEntryBase& entry,
|
|
||||||
wxEvtHandler *handler,
|
|
||||||
wxEvent& event)
|
|
||||||
{
|
{
|
||||||
int tableId1 = entry.m_id,
|
int tableId1 = entry.m_id,
|
||||||
tableId2 = entry.m_lastId;
|
tableId2 = entry.m_lastId;
|
||||||
@@ -1412,7 +1414,6 @@ bool wxEvtHandler::SafelyProcessEvent(wxEvent& event)
|
|||||||
#endif // wxUSE_EXCEPTIONS
|
#endif // wxUSE_EXCEPTIONS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event)
|
bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event)
|
||||||
{
|
{
|
||||||
const wxEventType eventType = event.GetEventType();
|
const wxEventType eventType = event.GetEventType();
|
||||||
|
@@ -56,116 +56,6 @@ void wxEventLoopBase::OnExit()
|
|||||||
wxTheApp->OnEventLoopExit(this);
|
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()
|
void wxEventLoopBase::WakeUpIdle()
|
||||||
{
|
{
|
||||||
WakeUp();
|
WakeUp();
|
||||||
@@ -173,13 +63,17 @@ void wxEventLoopBase::WakeUpIdle()
|
|||||||
|
|
||||||
bool wxEventLoopBase::ProcessIdle()
|
bool wxEventLoopBase::ProcessIdle()
|
||||||
{
|
{
|
||||||
|
if (!wxTheApp)
|
||||||
|
return false;
|
||||||
|
|
||||||
// process pending wx events before sending idle events
|
// process pending wx events before sending idle events
|
||||||
ProcessPendingEvents();
|
wxTheApp->ProcessPendingEvents();
|
||||||
|
|
||||||
|
// synthetize an idle event and send it to wxApp
|
||||||
wxIdleEvent event;
|
wxIdleEvent event;
|
||||||
|
|
||||||
event.SetEventObject(wxTheApp);
|
event.SetEventObject(wxTheApp);
|
||||||
wxTheApp->ProcessEvent(event);
|
wxTheApp->ProcessEvent(event);
|
||||||
|
|
||||||
return event.MoreRequested();
|
return event.MoreRequested();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user