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