#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();
// 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
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
// -------------
// 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;
//@}
+ /**
+ @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.
@library{wxbase}
@category{events}
- @see @ref overview_events_processing
+ @see @ref overview_events_processing, wxEventBlocker, wxEventLoopBase
*/
class wxEvtHandler : public wxObject
{
//@}
- /**
- @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
*/
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();
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
// ----------------------------------------------------------------------------
#if wxUSE_GUI
-/*
- * Command events
- *
- */
+// ----------------------------------------------------------------------------
+// wxCommandEvent
+// ----------------------------------------------------------------------------
#ifdef __VISUALC__
// 'this' : used in base member initializer list (for m_commandString)
}
}
-/*
- * UI update events
- */
+// ----------------------------------------------------------------------------
+// wxUpdateUIEvent
+// ----------------------------------------------------------------------------
#if wxUSE_LONGLONG
wxLongLong wxUpdateUIEvent::sm_lastUpdate = 0;
#endif
}
-/*
- * Scroll events
- */
+// ----------------------------------------------------------------------------
+// wxScrollEvent
+// ----------------------------------------------------------------------------
wxScrollEvent::wxScrollEvent(wxEventType commandType,
int id,
m_commandInt = pos;
}
-/*
- * ScrollWin events
- */
+// ----------------------------------------------------------------------------
+// wxScrollWinEvent
+// ----------------------------------------------------------------------------
wxScrollWinEvent::wxScrollWinEvent(wxEventType commandType,
int pos,
m_commandInt = pos;
}
-/*
- * Mouse events
- *
- */
+// ----------------------------------------------------------------------------
+// wxMouseEvent
+// ----------------------------------------------------------------------------
wxMouseEvent::wxMouseEvent(wxEventType commandType)
{
return pt;
}
-
-/*
- * Keyboard event
- *
- */
+// ----------------------------------------------------------------------------
+// wxKeyEvent
+// ----------------------------------------------------------------------------
wxKeyEvent::wxKeyEvent(wxEventType type)
{
#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)
{
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 )
{
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;
// 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
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;
}
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()
{
// 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 );
// 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;
#endif // wxUSE_EXCEPTIONS
}
-
bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event)
{
const wxEventType eventType = event.GetEventType();
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();
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();
}