]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/common/evtloopcmn.cpp
Fix wxHtmlHelpData::SetTempDir() to behave correctly without trailing slash.
[wxWidgets.git] / src / common / evtloopcmn.cpp
... / ...
CommitLineData
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
32wxEventLoopBase *wxEventLoopBase::ms_activeLoop = NULL;
33
34wxEventLoopBase::wxEventLoopBase()
35{
36 m_isInsideRun = false;
37 m_shouldExit = false;
38
39 m_isInsideYield = false;
40 m_eventsToProcessInsideYield = wxEVT_CATEGORY_ALL;
41}
42
43bool wxEventLoopBase::IsMain() const
44{
45 if (wxTheApp)
46 return wxTheApp->GetMainLoop() == this;
47 return false;
48}
49
50/* static */
51void wxEventLoopBase::SetActive(wxEventLoopBase* loop)
52{
53 ms_activeLoop = loop;
54
55 if (wxTheApp)
56 wxTheApp->OnEventLoopEnter(loop);
57}
58
59int 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
81void wxEventLoopBase::Exit(int rc)
82{
83 wxCHECK_RET( IsRunning(), wxS("Use ScheduleExit() on not running loop") );
84
85 ScheduleExit(rc);
86}
87
88void wxEventLoopBase::OnExit()
89{
90 if (wxTheApp)
91 wxTheApp->OnEventLoopExit(this);
92}
93
94void wxEventLoopBase::WakeUpIdle()
95{
96 WakeUp();
97}
98
99bool wxEventLoopBase::ProcessIdle()
100{
101 return wxTheApp && wxTheApp->ProcessIdle();
102}
103
104bool 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
121wxEventLoopSource*
122wxEventLoopBase::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
147wxEventLoopManual::wxEventLoopManual()
148{
149 m_exitcode = 0;
150}
151
152bool 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
175int 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
270void 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