]> git.saurik.com Git - wxWidgets.git/blame - src/common/evtloopcmn.cpp
Fix wxHtmlHelpData::SetTempDir() to behave correctly without trailing slash.
[wxWidgets.git] / src / common / evtloopcmn.cpp
CommitLineData
c8026dea
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/common/evtloopcmn.cpp
3// Purpose: common wxEventLoop-related stuff
4// Author: Vadim Zeitlin
c8026dea 5// Created: 2006-01-12
821d856a
VZ
6// Copyright: (c) 2006, 2013 Vadim Zeitlin <vadim@wxwindows.org>
7// (c) 2013 Rob Bresalier
c8026dea
VZ
8// Licence: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
c8026dea
VZ
11// for compilers that support precompilation, includes "wx.h".
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
15 #pragma hdrstop
16#endif
17
1e04d2bf
PC
18#include "wx/evtloop.h"
19
670f9935
WS
20#ifndef WX_PRECOMP
21 #include "wx/app.h"
22#endif //WX_PRECOMP
c8026dea 23
d3ad22bd 24#include "wx/scopeguard.h"
71e9885b
VZ
25#include "wx/apptrait.h"
26#include "wx/private/eventloopsourcesmanager.h"
d3ad22bd 27
c8026dea 28// ----------------------------------------------------------------------------
8b93348e 29// wxEventLoopBase
c8026dea
VZ
30// ----------------------------------------------------------------------------
31
2ddff00c 32wxEventLoopBase *wxEventLoopBase::ms_activeLoop = NULL;
c8026dea 33
dde19c21
FM
34wxEventLoopBase::wxEventLoopBase()
35{
d3ad22bd 36 m_isInsideRun = false;
a1fe5f90
VZ
37 m_shouldExit = false;
38
dde19c21
FM
39 m_isInsideYield = false;
40 m_eventsToProcessInsideYield = wxEVT_CATEGORY_ALL;
41}
42
ec38d07d
FM
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
c738d187
VZ
59int wxEventLoopBase::Run()
60{
61 // event loops are not recursive, you need to create another loop!
d3ad22bd 62 wxCHECK_MSG( !IsInsideRun(), -1, wxT("can't reenter a message loop") );
c738d187
VZ
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
d3ad22bd
VZ
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
c738d187
VZ
77 // Finally really run the loop.
78 return DoRun();
79}
80
d3ad22bd
VZ
81void wxEventLoopBase::Exit(int rc)
82{
83 wxCHECK_RET( IsRunning(), wxS("Use ScheduleExit() on not running loop") );
84
85 ScheduleExit(rc);
86}
87
ec38d07d
FM
88void wxEventLoopBase::OnExit()
89{
90 if (wxTheApp)
91 wxTheApp->OnEventLoopExit(this);
92}
93
dde19c21
FM
94void wxEventLoopBase::WakeUpIdle()
95{
96 WakeUp();
97}
98
99bool wxEventLoopBase::ProcessIdle()
100{
a758f601 101 return wxTheApp && wxTheApp->ProcessIdle();
dde19c21
FM
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
71e9885b
VZ
119#if wxUSE_EVENTLOOP_SOURCE
120
121wxEventLoopSource*
122wxEventLoopBase::AddSourceForFD(int fd,
123 wxEventLoopSourceHandler *handler,
124 int flags)
125{
ccf8bf20 126#if wxUSE_CONSOLE_EVENTLOOP
76015a6b 127 // Delegate to the event loop sources manager defined by it.
71e9885b 128 wxEventLoopSourcesManagerBase* const
76015a6b 129 manager = wxApp::GetValidTraits().GetEventLoopSourcesManager();
71e9885b
VZ
130 wxCHECK_MSG( manager, NULL, wxS("Must have wxEventLoopSourcesManager") );
131
132 return manager->AddSourceForFD(fd, handler, flags);
ccf8bf20
VZ
133#else // !wxUSE_CONSOLE_EVENTLOOP
134 return NULL;
135#endif // wxUSE_CONSOLE_EVENTLOOP/!wxUSE_CONSOLE_EVENTLOOP
71e9885b
VZ
136}
137
138#endif // wxUSE_EVENTLOOP_SOURCE
139
52c9b349 140// wxEventLoopManual is unused in the other ports
d98a58c5 141#if defined(__WINDOWS__) || defined(__WXDFB__) || ( ( defined(__UNIX__) && !defined(__WXOSX__) ) && wxUSE_BASE)
52c9b349 142
c8026dea
VZ
143// ============================================================================
144// wxEventLoopManual implementation
145// ============================================================================
146
147wxEventLoopManual::wxEventLoopManual()
148{
149 m_exitcode = 0;
c8026dea
VZ
150}
151
26bacb82
VZ
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 )
586c4551 162 {
26bacb82
VZ
163 wxTheApp->ProcessPendingEvents();
164
586c4551
VZ
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).
34c5aaa7 168 if ( m_shouldExit )
586c4551 169 return false;
586c4551
VZ
170 }
171
26bacb82
VZ
172 return Dispatch();
173}
174
c738d187 175int wxEventLoopManual::DoRun()
c8026dea 176{
c8026dea 177 // we must ensure that OnExit() is called even if an exception is thrown
26bacb82 178 // from inside ProcessEvents() but we must call it from Exit() in normal
c8026dea
VZ
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
34c5aaa7 197 while ( !m_shouldExit && !Pending() && ProcessIdle() )
c8026dea
VZ
198 ;
199
c8026dea 200 if ( m_shouldExit )
c8026dea 201 break;
c8026dea 202
26bacb82
VZ
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() )
c8026dea
VZ
207 {
208 // we got WM_QUIT
209 break;
210 }
211 }
212
34c5aaa7
VZ
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
c8026dea
VZ
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
d3ad22bd 270void wxEventLoopManual::ScheduleExit(int rc)
c8026dea 271{
d3ad22bd 272 wxCHECK_RET( IsInsideRun(), wxT("can't call ScheduleExit() if not running") );
c8026dea
VZ
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
d98a58c5 290#endif // __WINDOWS__ || __WXMAC__ || __WXDFB__
9af42efd 291