1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/evtloopcmn.cpp
3 // Purpose: common wxEventLoop-related stuff
4 // Author: Vadim Zeitlin
6 // Copyright: (c) 2006, 2013 Vadim Zeitlin <vadim@wxwindows.org>
7 // (c) 2013 Rob Bresalier
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 // for compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
18 #include "wx/evtloop.h"
24 #include "wx/scopeguard.h"
25 #include "wx/apptrait.h"
26 #include "wx/private/eventloopsourcesmanager.h"
28 // ----------------------------------------------------------------------------
30 // ----------------------------------------------------------------------------
32 wxEventLoopBase
*wxEventLoopBase::ms_activeLoop
= NULL
;
34 wxEventLoopBase::wxEventLoopBase()
36 m_isInsideRun
= false;
39 m_isInsideYield
= false;
40 m_eventsToProcessInsideYield
= wxEVT_CATEGORY_ALL
;
43 bool wxEventLoopBase::IsMain() const
46 return wxTheApp
->GetMainLoop() == this;
51 void wxEventLoopBase::SetActive(wxEventLoopBase
* loop
)
56 wxTheApp
->OnEventLoopEnter(loop
);
59 int wxEventLoopBase::Run()
61 // event loops are not recursive, you need to create another loop!
62 wxCHECK_MSG( !IsInsideRun(), -1, wxT("can't reenter a message loop") );
64 // ProcessIdle() and ProcessEvents() below may throw so the code here should
65 // be exception-safe, hence we must use local objects for all actions we
67 wxEventLoopActivator
activate(this);
69 // We might be called again, after a previous call to ScheduleExit(), so
73 // Set this variable to true for the duration of this method.
75 wxON_BLOCK_EXIT_SET(m_isInsideRun
, false);
77 // Finally really run the loop.
81 void wxEventLoopBase::Exit(int rc
)
83 wxCHECK_RET( IsRunning(), wxS("Use ScheduleExit() on not running loop") );
88 void wxEventLoopBase::OnExit()
91 wxTheApp
->OnEventLoopExit(this);
94 void wxEventLoopBase::WakeUpIdle()
99 bool wxEventLoopBase::ProcessIdle()
101 return wxTheApp
&& wxTheApp
->ProcessIdle();
104 bool wxEventLoopBase::Yield(bool onlyIfNeeded
)
106 if ( m_isInsideYield
)
110 wxFAIL_MSG( wxT("wxYield called recursively" ) );
116 return YieldFor(wxEVT_CATEGORY_ALL
);
119 #if wxUSE_EVENTLOOP_SOURCE
122 wxEventLoopBase::AddSourceForFD(int fd
,
123 wxEventLoopSourceHandler
*handler
,
126 #if wxUSE_CONSOLE_EVENTLOOP
127 // Delegate to the event loop sources manager defined by it.
128 wxEventLoopSourcesManagerBase
* const
129 manager
= wxApp::GetValidTraits().GetEventLoopSourcesManager();
130 wxCHECK_MSG( manager
, NULL
, wxS("Must have wxEventLoopSourcesManager") );
132 return manager
->AddSourceForFD(fd
, handler
, flags
);
133 #else // !wxUSE_CONSOLE_EVENTLOOP
135 #endif // wxUSE_CONSOLE_EVENTLOOP/!wxUSE_CONSOLE_EVENTLOOP
138 #endif // wxUSE_EVENTLOOP_SOURCE
140 // wxEventLoopManual is unused in the other ports
141 #if defined(__WINDOWS__) || defined(__WXDFB__) || ( ( defined(__UNIX__) && !defined(__WXOSX__) ) && wxUSE_BASE)
143 // ============================================================================
144 // wxEventLoopManual implementation
145 // ============================================================================
147 wxEventLoopManual::wxEventLoopManual()
152 bool wxEventLoopManual::ProcessEvents()
154 // process pending wx events first as they correspond to low-level events
155 // which happened before, i.e. typically pending events were queued by a
156 // previous call to Dispatch() and if we didn't process them now the next
157 // call to it might enqueue them again (as happens with e.g. socket events
158 // which would be generated as long as there is input available on socket
159 // and this input is only removed from it when pending event handlers are
163 wxTheApp
->ProcessPendingEvents();
165 // One of the pending event handlers could have decided to exit the
166 // loop so check for the flag before trying to dispatch more events
167 // (which could block indefinitely if no more are coming).
175 int wxEventLoopManual::DoRun()
177 // we must ensure that OnExit() is called even if an exception is thrown
178 // from inside ProcessEvents() but we must call it from Exit() in normal
179 // situations because it is supposed to be called synchronously,
180 // wxModalEventLoop depends on this (so we can't just use ON_BLOCK_EXIT or
181 // something similar here)
187 #endif // wxUSE_EXCEPTIONS
189 // this is the event loop itself
192 // give them the possibility to do whatever they want
195 // generate and process idle events for as long as we don't
196 // have anything else to do
197 while ( !m_shouldExit
&& !Pending() && ProcessIdle() )
203 // a message came or no more idle processing to do, dispatch
204 // all the pending events and call Dispatch() to wait for the
206 if ( !ProcessEvents() )
213 // Process the remaining queued messages, both at the level of the
214 // underlying toolkit level (Pending/Dispatch()) and wx level
215 // (Has/ProcessPendingEvents()).
217 // We do run the risk of never exiting this loop if pending event
218 // handlers endlessly generate new events but they shouldn't do
219 // this in a well-behaved program and we shouldn't just discard the
220 // events we already have, they might be important.
223 bool hasMoreEvents
= false;
224 if ( wxTheApp
&& wxTheApp
->HasPendingEvents() )
226 wxTheApp
->ProcessPendingEvents();
227 hasMoreEvents
= true;
233 hasMoreEvents
= true;
236 if ( !hasMoreEvents
)
241 // exit the outer loop as well
248 if ( !wxTheApp
|| !wxTheApp
->OnExceptionInMainLoop() )
253 //else: continue running the event loop
257 // OnException() throwed, possibly rethrowing the same
258 // exception again: very good, but we still need OnExit() to
265 #endif // wxUSE_EXCEPTIONS
270 void wxEventLoopManual::ScheduleExit(int rc
)
272 wxCHECK_RET( IsInsideRun(), wxT("can't call ScheduleExit() if not running") );
279 // all we have to do to exit from the loop is to (maybe) wake it up so that
280 // it can notice that Exit() had been called
282 // in particular, do *not* use here calls such as PostQuitMessage() (under
283 // MSW) which terminate the current event loop here because we're not sure
284 // that it is going to be processed by the correct event loop: it would be
285 // possible that another one is started and terminated by mistake if we do
290 #endif // __WINDOWS__ || __WXMAC__ || __WXDFB__