]> git.saurik.com Git - wxWidgets.git/blob - src/common/evtloopcmn.cpp
wxMessageBox off the main thread lost result code.
[wxWidgets.git] / src / common / evtloopcmn.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/evtloopcmn.cpp
3 // Purpose: common wxEventLoop-related stuff
4 // Author: Vadim Zeitlin
5 // Created: 2006-01-12
6 // Copyright: (c) 2006, 2013 Vadim Zeitlin <vadim@wxwindows.org>
7 // (c) 2013 Rob Bresalier
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // for compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17
18 #include "wx/evtloop.h"
19
20 #ifndef WX_PRECOMP
21 #include "wx/app.h"
22 #endif //WX_PRECOMP
23
24 #include "wx/scopeguard.h"
25 #include "wx/apptrait.h"
26 #include "wx/private/eventloopsourcesmanager.h"
27
28 // ----------------------------------------------------------------------------
29 // wxEventLoopBase
30 // ----------------------------------------------------------------------------
31
32 wxEventLoopBase *wxEventLoopBase::ms_activeLoop = NULL;
33
34 wxEventLoopBase::wxEventLoopBase()
35 {
36 m_isInsideRun = false;
37 m_shouldExit = false;
38
39 m_isInsideYield = false;
40 m_eventsToProcessInsideYield = wxEVT_CATEGORY_ALL;
41 }
42
43 bool wxEventLoopBase::IsMain() const
44 {
45 if (wxTheApp)
46 return wxTheApp->GetMainLoop() == this;
47 return false;
48 }
49
50 /* static */
51 void wxEventLoopBase::SetActive(wxEventLoopBase* loop)
52 {
53 ms_activeLoop = loop;
54
55 if (wxTheApp)
56 wxTheApp->OnEventLoopEnter(loop);
57 }
58
59 int wxEventLoopBase::Run()
60 {
61 // event loops are not recursive, you need to create another loop!
62 wxCHECK_MSG( !IsInsideRun(), -1, wxT("can't reenter a message loop") );
63
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
66 // should undo
67 wxEventLoopActivator activate(this);
68
69 // We might be called again, after a previous call to ScheduleExit(), so
70 // reset this flag.
71 m_shouldExit = false;
72
73 // Set this variable to true for the duration of this method.
74 m_isInsideRun = true;
75 wxON_BLOCK_EXIT_SET(m_isInsideRun, false);
76
77 // Finally really run the loop.
78 return DoRun();
79 }
80
81 void wxEventLoopBase::Exit(int rc)
82 {
83 wxCHECK_RET( IsRunning(), wxS("Use ScheduleExit() on not running loop") );
84
85 ScheduleExit(rc);
86 }
87
88 void wxEventLoopBase::OnExit()
89 {
90 if (wxTheApp)
91 wxTheApp->OnEventLoopExit(this);
92 }
93
94 void wxEventLoopBase::WakeUpIdle()
95 {
96 WakeUp();
97 }
98
99 bool wxEventLoopBase::ProcessIdle()
100 {
101 return wxTheApp && wxTheApp->ProcessIdle();
102 }
103
104 bool wxEventLoopBase::Yield(bool onlyIfNeeded)
105 {
106 if ( m_isInsideYield )
107 {
108 if ( !onlyIfNeeded )
109 {
110 wxFAIL_MSG( wxT("wxYield called recursively" ) );
111 }
112
113 return false;
114 }
115
116 return YieldFor(wxEVT_CATEGORY_ALL);
117 }
118
119 #if wxUSE_EVENTLOOP_SOURCE
120
121 wxEventLoopSource*
122 wxEventLoopBase::AddSourceForFD(int fd,
123 wxEventLoopSourceHandler *handler,
124 int flags)
125 {
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") );
131
132 return manager->AddSourceForFD(fd, handler, flags);
133 #else // !wxUSE_CONSOLE_EVENTLOOP
134 return NULL;
135 #endif // wxUSE_CONSOLE_EVENTLOOP/!wxUSE_CONSOLE_EVENTLOOP
136 }
137
138 #endif // wxUSE_EVENTLOOP_SOURCE
139
140 // wxEventLoopManual is unused in the other ports
141 #if defined(__WINDOWS__) || defined(__WXDFB__) || ( ( defined(__UNIX__) && !defined(__WXOSX__) ) && wxUSE_BASE)
142
143 // ============================================================================
144 // wxEventLoopManual implementation
145 // ============================================================================
146
147 wxEventLoopManual::wxEventLoopManual()
148 {
149 m_exitcode = 0;
150 }
151
152 bool wxEventLoopManual::ProcessEvents()
153 {
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
160 // executed)
161 if ( wxTheApp )
162 {
163 wxTheApp->ProcessPendingEvents();
164
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).
168 if ( m_shouldExit )
169 return false;
170 }
171
172 return Dispatch();
173 }
174
175 int wxEventLoopManual::DoRun()
176 {
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)
182 #if wxUSE_EXCEPTIONS
183 for ( ;; )
184 {
185 try
186 {
187 #endif // wxUSE_EXCEPTIONS
188
189 // this is the event loop itself
190 for ( ;; )
191 {
192 // give them the possibility to do whatever they want
193 OnNextIteration();
194
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() )
198 ;
199
200 if ( m_shouldExit )
201 break;
202
203 // a message came or no more idle processing to do, dispatch
204 // all the pending events and call Dispatch() to wait for the
205 // next message
206 if ( !ProcessEvents() )
207 {
208 // we got WM_QUIT
209 break;
210 }
211 }
212
213 // Process the remaining queued messages, both at the level of the
214 // underlying toolkit level (Pending/Dispatch()) and wx level
215 // (Has/ProcessPendingEvents()).
216 //
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.
221 for ( ;; )
222 {
223 bool hasMoreEvents = false;
224 if ( wxTheApp && wxTheApp->HasPendingEvents() )
225 {
226 wxTheApp->ProcessPendingEvents();
227 hasMoreEvents = true;
228 }
229
230 if ( Pending() )
231 {
232 Dispatch();
233 hasMoreEvents = true;
234 }
235
236 if ( !hasMoreEvents )
237 break;
238 }
239
240 #if wxUSE_EXCEPTIONS
241 // exit the outer loop as well
242 break;
243 }
244 catch ( ... )
245 {
246 try
247 {
248 if ( !wxTheApp || !wxTheApp->OnExceptionInMainLoop() )
249 {
250 OnExit();
251 break;
252 }
253 //else: continue running the event loop
254 }
255 catch ( ... )
256 {
257 // OnException() throwed, possibly rethrowing the same
258 // exception again: very good, but we still need OnExit() to
259 // be called
260 OnExit();
261 throw;
262 }
263 }
264 }
265 #endif // wxUSE_EXCEPTIONS
266
267 return m_exitcode;
268 }
269
270 void wxEventLoopManual::ScheduleExit(int rc)
271 {
272 wxCHECK_RET( IsInsideRun(), wxT("can't call ScheduleExit() if not running") );
273
274 m_exitcode = rc;
275 m_shouldExit = true;
276
277 OnExit();
278
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
281 //
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
286 // this
287 WakeUp();
288 }
289
290 #endif // __WINDOWS__ || __WXMAC__ || __WXDFB__
291