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