Ensure that wxApp::Yield is always processing pending event by creating a
[wxWidgets.git] / include / wx / evtloop.h
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>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 #ifndef _WX_EVTLOOP_H_
13 #define _WX_EVTLOOP_H_
14
15 #include "wx/utils.h"
16
17 // ----------------------------------------------------------------------------
18 // wxEventLoopBase: interface for wxEventLoop
19 // ----------------------------------------------------------------------------
20
21 class WXDLLIMPEXP_BASE wxEventLoopBase
22 {
23 public:
24 // trivial, but needed (because of wxEventLoopBase) ctor
25 wxEventLoopBase() { }
26
27 // dtor
28 virtual ~wxEventLoopBase() { }
29
30 // use this to check whether the event loop was successfully created before
31 // using it
32 virtual bool IsOk() const { return true; }
33
34 // start the event loop, return the exit code when it is finished
35 virtual int Run() = 0;
36
37 // exit from the loop with the given exit code
38 virtual void Exit(int rc = 0) = 0;
39
40 // return true if any events are available
41 virtual bool Pending() const = 0;
42
43 // dispatch a single event, return false if we should exit from the loop
44 virtual bool Dispatch() = 0;
45
46 // return currently active (running) event loop, may be NULL
47 static wxEventLoopBase *GetActive() { return ms_activeLoop; }
48
49 // set currently active (running) event loop
50 static void SetActive(wxEventLoopBase* loop) { ms_activeLoop = loop; }
51
52 // is this event loop running now?
53 //
54 // notice that even if this event loop hasn't terminated yet but has just
55 // spawned a nested (e.g. modal) event loop, this would return false
56 bool IsRunning() const;
57
58 // implement this to wake up the loop: usually done by posting a dummy event
59 // to it (can be called from non main thread)
60 virtual void WakeUp() = 0;
61
62 protected:
63 // this function should be called before the event loop terminates, whether
64 // this happens normally (because of Exit() call) or abnormally (because of
65 // an exception thrown from inside the loop)
66 virtual void OnExit() { }
67
68
69 // the pointer to currently active loop
70 static wxEventLoopBase *ms_activeLoop;
71
72 DECLARE_NO_COPY_CLASS(wxEventLoopBase)
73 };
74
75 #if defined(__WXMSW__) || defined(__WXMAC__) || defined(__WXDFB__) || defined(__UNIX__)
76
77 // this class can be used to implement a standard event loop logic using
78 // Pending() and Dispatch()
79 //
80 // it also handles idle processing automatically
81 class WXDLLIMPEXP_BASE wxEventLoopManual : public wxEventLoopBase
82 {
83 public:
84 wxEventLoopManual();
85
86 // enters a loop calling OnNextIteration(), Pending() and Dispatch() and
87 // terminating when Exit() is called
88 virtual int Run();
89
90 // sets the "should exit" flag and wakes up the loop so that it terminates
91 // soon
92 virtual void Exit(int rc = 0);
93
94 protected:
95 // may be overridden to perform some action at the start of each new event
96 // loop iteration
97 virtual void OnNextIteration() { }
98
99
100 // the loop exit code
101 int m_exitcode;
102
103 // should we exit the loop?
104 bool m_shouldExit;
105 };
106
107 #endif // platforms using "manual" loop
108
109 // we're moving away from old m_impl wxEventLoop model as otherwise the user
110 // code doesn't have access to platform-specific wxEventLoop methods and this
111 // can sometimes be very useful (e.g. under MSW this is necessary for
112 // integration with MFC) but currently this is done for MSW only, other ports
113 // should follow a.s.a.p.
114 #if defined(__WXPALMOS__)
115 #include "wx/palmos/evtloop.h"
116 #elif defined(__WXMSW__)
117 #include "wx/msw/evtloop.h"
118 #elif defined(__WXMAC__)
119 #include "wx/mac/evtloop.h"
120 #elif defined(__WXDFB__)
121 #include "wx/dfb/evtloop.h"
122 #else // other platform
123
124 class WXDLLIMPEXP_FWD_CORE wxEventLoopImpl;
125
126 class WXDLLIMPEXP_CORE wxGUIEventLoop : public wxEventLoopBase
127 {
128 public:
129 wxGUIEventLoop() { m_impl = NULL; }
130 virtual ~wxGUIEventLoop();
131
132 virtual int Run();
133 virtual void Exit(int rc = 0);
134 virtual bool Pending() const;
135 virtual bool Dispatch();
136 virtual void WakeUp() { }
137
138 protected:
139 // the pointer to the port specific implementation class
140 wxEventLoopImpl *m_impl;
141
142 DECLARE_NO_COPY_CLASS(wxGUIEventLoop)
143 };
144
145 #endif // platforms
146
147 // also include the header defining wxConsoleEventLoop for Unix systems
148 #if defined(__UNIX__)
149 #include "wx/unix/evtloop.h"
150 #endif
151
152 // we use a class rather than a typedef because wxEventLoop is forward-declared
153 // in many places
154 #if wxUSE_GUI
155 class wxEventLoop : public wxGUIEventLoop { };
156 #else // !GUI
157 // we can't define wxEventLoop differently in GUI and base libraries so use
158 // a #define to still allow writing wxEventLoop in the user code
159 #if defined(__WXMSW__) || defined(__UNIX__)
160 #define wxEventLoop wxConsoleEventLoop
161 #else // we still must define it somehow for the code below...
162 #define wxEventLoop wxEventLoopBase
163 #endif
164 #endif
165
166 inline bool wxEventLoopBase::IsRunning() const { return GetActive() == this; }
167
168 #if wxUSE_GUI
169 // ----------------------------------------------------------------------------
170 // wxModalEventLoop
171 // ----------------------------------------------------------------------------
172
173 // this is a naive generic implementation which uses wxWindowDisabler to
174 // implement modality, we will surely need platform-specific implementations
175 // too, this generic implementation is here only temporarily to see how it
176 // works
177 class WXDLLIMPEXP_CORE wxModalEventLoop : public wxGUIEventLoop
178 {
179 public:
180 wxModalEventLoop(wxWindow *winModal)
181 {
182 m_windowDisabler = new wxWindowDisabler(winModal);
183 }
184
185 protected:
186 virtual void OnExit()
187 {
188 delete m_windowDisabler;
189 m_windowDisabler = NULL;
190
191 wxGUIEventLoop::OnExit();
192 }
193
194 private:
195 wxWindowDisabler *m_windowDisabler;
196 };
197
198 #endif //wxUSE_GUI
199
200 // ----------------------------------------------------------------------------
201 // wxEventLoopActivator: helper class for wxEventLoop implementations
202 // ----------------------------------------------------------------------------
203
204 // this object sets the wxEventLoop given to the ctor as the currently active
205 // one and unsets it in its dtor, this is especially useful in presence of
206 // exceptions but is more tidy even when we don't use them
207 class wxEventLoopActivator
208 {
209 public:
210 wxEventLoopActivator(wxEventLoopBase *evtLoop)
211 {
212 m_evtLoopOld = wxEventLoopBase::GetActive();
213 wxEventLoopBase::SetActive(evtLoop);
214 }
215
216 ~wxEventLoopActivator()
217 {
218 // restore the previously active event loop
219 wxEventLoopBase::SetActive(m_evtLoopOld);
220 }
221
222 private:
223 wxEventLoopBase *m_evtLoopOld;
224 };
225
226 class wxEventLoopGuarantor
227 {
228 public:
229 wxEventLoopGuarantor()
230 {
231 m_evtLoopNew = NULL;
232 if (!wxEventLoop::GetActive())
233 {
234 m_evtLoopNew = new wxEventLoop;
235 wxEventLoop::SetActive(m_evtLoopNew);
236 }
237 }
238
239 ~wxEventLoopGuarantor()
240 {
241 if (m_evtLoopNew)
242 {
243 wxEventLoop::SetActive(NULL);
244 delete m_evtLoopNew;
245 }
246 }
247
248 private:
249 wxEventLoop *m_evtLoopNew;
250 };
251
252 #endif // _WX_EVTLOOP_H_