]> git.saurik.com Git - wxWidgets.git/blame - include/wx/evtloop.h
Define WXBUILDING in Xcode projects.
[wxWidgets.git] / include / wx / evtloop.h
CommitLineData
3808e191
JS
1///////////////////////////////////////////////////////////////////////////////
2// Name: wx/evtloop.h
3// Purpose: declares wxEventLoop class
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 01.06.01
7// RCS-ID: $Id$
8// Copyright: (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
65571936 9// Licence: wxWindows licence
3808e191
JS
10///////////////////////////////////////////////////////////////////////////////
11
12#ifndef _WX_EVTLOOP_H_
13#define _WX_EVTLOOP_H_
14
1e04d2bf 15#include "wx/event.h"
752464f9 16#include "wx/utils.h"
6b8ef0b3 17
5cd99866
VZ
18// TODO: implement wxEventLoopSource for MSW (it should wrap a HANDLE and be
19// monitored using MsgWaitForMultipleObjects())
acbed114 20#if defined(__WXOSX__) || (defined(__UNIX__) && !defined(__WXMSW__))
6b8ef0b3
VZ
21 #define wxUSE_EVENTLOOP_SOURCE 1
22#else
23 #define wxUSE_EVENTLOOP_SOURCE 0
24#endif
25
26#if wxUSE_EVENTLOOP_SOURCE
5cd99866
VZ
27 class wxEventLoopSource;
28 class wxEventLoopSourceHandler;
6b8ef0b3
VZ
29#endif
30
dde19c21
FM
31/*
32 NOTE ABOUT wxEventLoopBase::YieldFor LOGIC
33 ------------------------------------------
34
35 The YieldFor() function helps to avoid re-entrancy problems and problems
36 caused by out-of-order event processing
37 (see "wxYield-like problems" and "wxProgressDialog+threading BUG" wx-dev threads).
38
39 The logic behind YieldFor() is simple: it analyzes the queue of the native
40 events generated by the underlying GUI toolkit and picks out and processes
41 only those matching the given mask.
42
43 It's important to note that YieldFor() is used to selectively process the
44 events generated by the NATIVE toolkit.
45 Events syntethized by wxWidgets code or by user code are instead selectively
46 processed thanks to the logic built into wxEvtHandler::ProcessPendingEvents().
47 In fact, when wxEvtHandler::ProcessPendingEvents gets called from inside a
48 YieldFor() call, wxEventLoopBase::IsEventAllowedInsideYield is used to decide
49 if the pending events for that event handler can be processed.
50 If all the pending events associated with that event handler result as "not processable",
51 the event handler "delays" itself calling wxEventLoopBase::DelayPendingEventHandler
52 (so it's moved: m_handlersWithPendingEvents => m_handlersWithPendingDelayedEvents).
53 Last, wxEventLoopBase::ProcessPendingEvents() before exiting moves the delayed
54 event handlers back into the list of handlers with pending events
55 (m_handlersWithPendingDelayedEvents => m_handlersWithPendingEvents) so that
56 a later call to ProcessPendingEvents() (possibly outside the YieldFor() call)
57 will process all pending events as usual.
58*/
59
3808e191 60// ----------------------------------------------------------------------------
b46b1d59 61// wxEventLoopBase: interface for wxEventLoop
3808e191
JS
62// ----------------------------------------------------------------------------
63
b46b1d59 64class WXDLLIMPEXP_BASE wxEventLoopBase
3808e191
JS
65{
66public:
3754265e 67 // trivial, but needed (because of wxEventLoopBase) ctor
dde19c21 68 wxEventLoopBase();
3808e191
JS
69
70 // dtor
3754265e 71 virtual ~wxEventLoopBase() { }
3808e191 72
b46b1d59
VZ
73 // use this to check whether the event loop was successfully created before
74 // using it
75 virtual bool IsOk() const { return true; }
76
ec38d07d
FM
77 // returns true if this is the main loop
78 bool IsMain() const;
79
6b8ef0b3 80#if wxUSE_EVENTLOOP_SOURCE
5cd99866 81 // create a new event loop source wrapping the given file descriptor and
71e9885b
VZ
82 // monitor it for events occurring on this descriptor in all event loops
83 static wxEventLoopSource *
84 AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags);
5cd99866 85#endif // wxUSE_EVENTLOOP_SOURCE
9af42efd 86
dde19c21
FM
87 // dispatch&processing
88 // -------------------
89
3808e191 90 // start the event loop, return the exit code when it is finished
c738d187
VZ
91 //
92 // notice that wx ports should override DoRun(), this method is virtual
93 // only to allow overriding it in the user code for custom event loops
94 virtual int Run();
3808e191 95
dde19c21
FM
96 // is this event loop running now?
97 //
98 // notice that even if this event loop hasn't terminated yet but has just
99 // spawned a nested (e.g. modal) event loop, this would return false
100 bool IsRunning() const;
101
3808e191 102 // exit from the loop with the given exit code
d3ad22bd
VZ
103 //
104 // this can be only used to exit the currently running loop, use
105 // ScheduleExit() if this might not be the case
106 virtual void Exit(int rc = 0);
107
108 // ask the event loop to exit with the given exit code, can be used even if
109 // this loop is not running right now but the loop must have been started,
110 // i.e. Run() should have been already called
111 virtual void ScheduleExit(int rc = 0) = 0;
3808e191 112
1a18887b 113 // return true if any events are available
3754265e 114 virtual bool Pending() const = 0;
3808e191 115
1a18887b 116 // dispatch a single event, return false if we should exit from the loop
3754265e 117 virtual bool Dispatch() = 0;
3808e191 118
9af42efd
VZ
119 // same as Dispatch() but doesn't wait for longer than the specified (in
120 // ms) timeout, return true if an event was processed, false if we should
121 // exit the loop or -1 if timeout expired
122 virtual int DispatchTimeout(unsigned long timeout) = 0;
123
dde19c21
FM
124 // implement this to wake up the loop: usually done by posting a dummy event
125 // to it (can be called from non main thread)
126 virtual void WakeUp() = 0;
127
128
dde19c21
FM
129 // idle handling
130 // -------------
131
a758f601 132 // make sure that idle events are sent again
dde19c21
FM
133 virtual void WakeUpIdle();
134
135 // this virtual function is called when the application
a758f601
VZ
136 // becomes idle and by default it forwards to wxApp::ProcessIdle() and
137 // while it can be overridden in a custom event loop, you must call the
138 // base class version to ensure that idle events are still generated
dde19c21
FM
139 //
140 // it should return true if more idle events are needed, false if not
141 virtual bool ProcessIdle();
142
143
144 // Yield-related hooks
145 // -------------------
146
6b8ef0b3
VZ
147 // process all currently pending events right now
148 //
149 // it is an error to call Yield() recursively unless the value of
150 // onlyIfNeeded is true
151 //
152 // WARNING: this function is dangerous as it can lead to unexpected
153 // reentrancies (i.e. when called from an event handler it
154 // may result in calling the same event handler again), use
155 // with _extreme_ care or, better, don't use at all!
dde19c21
FM
156 bool Yield(bool onlyIfNeeded = false);
157 virtual bool YieldFor(long eventsToProcess) = 0;
158
6b8ef0b3 159 // returns true if the main thread is inside a Yield() call
dde19c21
FM
160 virtual bool IsYielding() const
161 { return m_isInsideYield; }
162
6b8ef0b3
VZ
163 // returns true if events of the given event category should be immediately
164 // processed inside a wxApp::Yield() call or rather should be queued for
165 // later processing by the main event loop
dde19c21
FM
166 virtual bool IsEventAllowedInsideYield(wxEventCategory cat) const
167 { return (m_eventsToProcessInsideYield & cat) != 0; }
168
169 // no SafeYield hooks since it uses wxWindow which is not available when wxUSE_GUI=0
170
171
172 // active loop
173 // -----------
9af42efd 174
b9f246f7 175 // return currently active (running) event loop, may be NULL
2ddff00c 176 static wxEventLoopBase *GetActive() { return ms_activeLoop; }
3808e191 177
df0e1b64 178 // set currently active (running) event loop
ec38d07d 179 static void SetActive(wxEventLoopBase* loop);
df0e1b64 180
b46b1d59 181
3808e191 182protected:
c738d187
VZ
183 // real implementation of Run()
184 virtual int DoRun() = 0;
185
4300caa7
VZ
186 // this function should be called before the event loop terminates, whether
187 // this happens normally (because of Exit() call) or abnormally (because of
188 // an exception thrown from inside the loop)
ec38d07d 189 virtual void OnExit();
4300caa7 190
d3ad22bd
VZ
191 // Return true if we're currently inside our Run(), even if another nested
192 // event loop is currently running, unlike IsRunning() (which should have
193 // been really called IsActive() but it's too late to change this now).
194 bool IsInsideRun() const { return m_isInsideRun; }
195
196
b9f246f7 197 // the pointer to currently active loop
2ddff00c 198 static wxEventLoopBase *ms_activeLoop;
22f3361e 199
a1fe5f90
VZ
200 // should we exit the loop?
201 bool m_shouldExit;
202
8e40ed85 203 // YieldFor() helpers:
dde19c21
FM
204 bool m_isInsideYield;
205 long m_eventsToProcessInsideYield;
206
d3ad22bd
VZ
207private:
208 // this flag is set on entry into Run() and reset before leaving it
209 bool m_isInsideRun;
210
c0c133e1 211 wxDECLARE_NO_COPY_CLASS(wxEventLoopBase);
3754265e
VZ
212};
213
e27f5540 214#if defined(__WINDOWS__) || defined(__WXMAC__) || defined(__WXDFB__) || (defined(__UNIX__) && !defined(__WXOSX__))
c8026dea
VZ
215
216// this class can be used to implement a standard event loop logic using
217// Pending() and Dispatch()
218//
219// it also handles idle processing automatically
b46b1d59 220class WXDLLIMPEXP_BASE wxEventLoopManual : public wxEventLoopBase
c8026dea
VZ
221{
222public:
223 wxEventLoopManual();
224
c8026dea
VZ
225 // sets the "should exit" flag and wakes up the loop so that it terminates
226 // soon
d3ad22bd 227 virtual void ScheduleExit(int rc = 0);
c8026dea
VZ
228
229protected:
c738d187
VZ
230 // enters a loop calling OnNextIteration(), Pending() and Dispatch() and
231 // terminating when Exit() is called
232 virtual int DoRun();
233
c8026dea
VZ
234 // may be overridden to perform some action at the start of each new event
235 // loop iteration
236 virtual void OnNextIteration() { }
237
238
239 // the loop exit code
240 int m_exitcode;
241
2a392e2d 242private:
26bacb82
VZ
243 // process all already pending events and dispatch a new one (blocking
244 // until it appears in the event queue if necessary)
245 //
246 // returns the return value of Dispatch()
247 bool ProcessEvents();
248
2a392e2d 249 wxDECLARE_NO_COPY_CLASS(wxEventLoopManual);
c8026dea
VZ
250};
251
252#endif // platforms using "manual" loop
253
3754265e
VZ
254// we're moving away from old m_impl wxEventLoop model as otherwise the user
255// code doesn't have access to platform-specific wxEventLoop methods and this
256// can sometimes be very useful (e.g. under MSW this is necessary for
5cd99866
VZ
257// integration with MFC) but currently this is not done for all ports yet (e.g.
258// wxX11) so fall back to the old wxGUIEventLoop definition below for them
259
da0ee16e 260#if defined(__DARWIN__)
5cd99866
VZ
261 // CoreFoundation-based event loop is currently in wxBase so include it in
262 // any case too (although maybe it actually shouldn't be there at all)
7ce6da52
VZ
263 #include "wx/osx/core/evtloop.h"
264#endif
265
266// include the header defining wxConsoleEventLoop
267#if defined(__UNIX__) && !defined(__WXMSW__)
268 #include "wx/unix/evtloop.h"
269#elif defined(__WINDOWS__)
270 #include "wx/msw/evtloopconsole.h"
271#endif
272
273#if wxUSE_GUI
5cd99866
VZ
274
275// include the appropriate header defining wxGUIEventLoop
276
e27f5540
VZ
277#if defined(__WXMSW__)
278 #include "wx/msw/evtloop.h"
279#elif defined(__WXCOCOA__)
1df4b194 280 #include "wx/cocoa/evtloop.h"
7ce6da52
VZ
281#elif defined(__WXOSX__)
282 #include "wx/osx/evtloop.h"
b3c86150
VS
283#elif defined(__WXDFB__)
284 #include "wx/dfb/evtloop.h"
bc7879ec 285#elif defined(__WXGTK20__)
564c7fc4 286 #include "wx/gtk/evtloop.h"
4d90072c 287#else // other platform
3754265e 288
9c26672d 289#include "wx/stopwatch.h" // for wxMilliClock_t
9af42efd 290
b5dbe15d 291class WXDLLIMPEXP_FWD_CORE wxEventLoopImpl;
3754265e 292
53a2db12 293class WXDLLIMPEXP_CORE wxGUIEventLoop : public wxEventLoopBase
3754265e
VZ
294{
295public:
b46b1d59
VZ
296 wxGUIEventLoop() { m_impl = NULL; }
297 virtual ~wxGUIEventLoop();
1a18887b 298
d3ad22bd 299 virtual void ScheduleExit(int rc = 0);
3754265e
VZ
300 virtual bool Pending() const;
301 virtual bool Dispatch();
9c26672d
VZ
302 virtual int DispatchTimeout(unsigned long timeout)
303 {
304 // TODO: this is, of course, horribly inefficient and a proper wait with
305 // timeout should be implemented for all ports natively...
306 const wxMilliClock_t timeEnd = wxGetLocalTimeMillis() + timeout;
307 for ( ;; )
308 {
309 if ( Pending() )
310 return Dispatch();
311
312 if ( wxGetLocalTimeMillis() >= timeEnd )
313 return -1;
314 }
315 }
b46b1d59 316 virtual void WakeUp() { }
dde19c21 317 virtual bool YieldFor(long eventsToProcess);
3754265e
VZ
318
319protected:
c738d187
VZ
320 virtual int DoRun();
321
4300caa7
VZ
322 // the pointer to the port specific implementation class
323 wxEventLoopImpl *m_impl;
324
c0c133e1 325 wxDECLARE_NO_COPY_CLASS(wxGUIEventLoop);
4d90072c 326};
3754265e 327
4d90072c 328#endif // platforms
3808e191 329
5cd99866 330#endif // wxUSE_GUI
b46b1d59 331
b46b1d59 332#if wxUSE_GUI
5cd99866
VZ
333 // we use a class rather than a typedef because wxEventLoop is
334 // forward-declared in many places
2ddff00c 335 class wxEventLoop : public wxGUIEventLoop { };
5cd99866 336#else // !wxUSE_GUI
2ddff00c
VZ
337 // we can't define wxEventLoop differently in GUI and base libraries so use
338 // a #define to still allow writing wxEventLoop in the user code
e27f5540 339 #if wxUSE_CONSOLE_EVENTLOOP && (defined(__WINDOWS__) || defined(__UNIX__))
2ddff00c
VZ
340 #define wxEventLoop wxConsoleEventLoop
341 #else // we still must define it somehow for the code below...
342 #define wxEventLoop wxEventLoopBase
343 #endif
b46b1d59
VZ
344#endif
345
77fb1a02
VZ
346inline bool wxEventLoopBase::IsRunning() const { return GetActive() == this; }
347
80eee837 348#if wxUSE_GUI && !defined(__WXOSX__)
4300caa7
VZ
349// ----------------------------------------------------------------------------
350// wxModalEventLoop
351// ----------------------------------------------------------------------------
352
353// this is a naive generic implementation which uses wxWindowDisabler to
354// implement modality, we will surely need platform-specific implementations
355// too, this generic implementation is here only temporarily to see how it
356// works
53a2db12 357class WXDLLIMPEXP_CORE wxModalEventLoop : public wxGUIEventLoop
4300caa7
VZ
358{
359public:
360 wxModalEventLoop(wxWindow *winModal)
361 {
362 m_windowDisabler = new wxWindowDisabler(winModal);
363 }
364
365protected:
366 virtual void OnExit()
367 {
368 delete m_windowDisabler;
369 m_windowDisabler = NULL;
370
b46b1d59 371 wxGUIEventLoop::OnExit();
4300caa7
VZ
372 }
373
374private:
375 wxWindowDisabler *m_windowDisabler;
376};
377
b46b1d59
VZ
378#endif //wxUSE_GUI
379
77fb1a02
VZ
380// ----------------------------------------------------------------------------
381// wxEventLoopActivator: helper class for wxEventLoop implementations
382// ----------------------------------------------------------------------------
383
384// this object sets the wxEventLoop given to the ctor as the currently active
385// one and unsets it in its dtor, this is especially useful in presence of
386// exceptions but is more tidy even when we don't use them
387class wxEventLoopActivator
388{
389public:
b46b1d59 390 wxEventLoopActivator(wxEventLoopBase *evtLoop)
77fb1a02 391 {
b46b1d59 392 m_evtLoopOld = wxEventLoopBase::GetActive();
2ddff00c 393 wxEventLoopBase::SetActive(evtLoop);
77fb1a02
VZ
394 }
395
396 ~wxEventLoopActivator()
397 {
398 // restore the previously active event loop
b46b1d59 399 wxEventLoopBase::SetActive(m_evtLoopOld);
77fb1a02
VZ
400 }
401
402private:
2ddff00c 403 wxEventLoopBase *m_evtLoopOld;
77fb1a02
VZ
404};
405
1a7cfc94
VZ
406#if wxUSE_CONSOLE_EVENTLOOP
407
f212e222
SN
408class wxEventLoopGuarantor
409{
410public:
411 wxEventLoopGuarantor()
412 {
413 m_evtLoopNew = NULL;
414 if (!wxEventLoop::GetActive())
415 {
416 m_evtLoopNew = new wxEventLoop;
417 wxEventLoop::SetActive(m_evtLoopNew);
418 }
419 }
420
421 ~wxEventLoopGuarantor()
422 {
423 if (m_evtLoopNew)
424 {
425 wxEventLoop::SetActive(NULL);
426 delete m_evtLoopNew;
427 }
428 }
429
430private:
431 wxEventLoop *m_evtLoopNew;
432};
433
1a7cfc94
VZ
434#endif // wxUSE_CONSOLE_EVENTLOOP
435
3808e191 436#endif // _WX_EVTLOOP_H_