]>
Commit | Line | Data |
---|---|---|
1 | ///////////////////////////////////////////////////////////////////////////// | |
2 | // Name: wx/evtloop.h | |
3 | // Purpose: wxEventLoop and related classes | |
4 | // Author: Vadim Zeitlin | |
5 | // Copyright: (C) 2008 Vadim Zeitlin | |
6 | // Licence: wxWindows licence | |
7 | ///////////////////////////////////////////////////////////////////////////// | |
8 | ||
9 | /** | |
10 | @class wxEventLoopBase | |
11 | ||
12 | Base class for all event loop implementations. | |
13 | ||
14 | An event loop is a class which queries the queue of native events sent | |
15 | to the wxWidgets application and dispatches them to the appropriate | |
16 | wxEvtHandlers. | |
17 | ||
18 | An object of this class is created by wxAppTraits::CreateEventLoop() and | |
19 | used by wxApp to run the main application event loop. | |
20 | Temporary event loops are usually created by wxDialog::ShowModal(). | |
21 | ||
22 | You can create your own event loop if you need, provided that you restore | |
23 | the main event loop once yours is destroyed (see wxEventLoopActivator). | |
24 | ||
25 | Notice that there can be more than one event loop at any given moment, e.g. | |
26 | an event handler called from the main loop can show a modal dialog, which | |
27 | starts its own loop resulting in two nested loops, with the modal dialog | |
28 | being the active one (its IsRunning() returns @true). And a handler for a | |
29 | button inside the modal dialog can, of course, create another modal dialog | |
30 | with its own event loop and so on. So in general event loops form a stack | |
31 | and only the event loop at the top of the stack is considered to be active. | |
32 | It is also the only loop that can be directly asked to terminate by calling | |
33 | Exit() (which is done by wxDialog::EndModal()), an outer event loop can't | |
34 | be stopped while an inner one is still running. It is however possible to | |
35 | ask an outer event loop to terminate as soon as all its nested loops exit | |
36 | and the control returns back to it by using ScheduleExit(). | |
37 | ||
38 | @library{wxbase} | |
39 | @category{appmanagement} | |
40 | ||
41 | @see wxApp, wxEventLoopActivator | |
42 | */ | |
43 | class wxEventLoopBase | |
44 | { | |
45 | public: | |
46 | /** | |
47 | Return the currently active (running) event loop. | |
48 | ||
49 | May return @NULL if there is no active event loop (e.g. during | |
50 | application startup or shutdown). | |
51 | */ | |
52 | static wxEventLoopBase *GetActive(); | |
53 | ||
54 | /** | |
55 | Set currently active (running) event loop. | |
56 | ||
57 | Called by wxEventLoopActivator, use an instance of this class instead | |
58 | of calling this method directly to ensure that the previously active | |
59 | event loop is restored. | |
60 | ||
61 | Results in a call to wxAppConsole::OnEventLoopEnter. | |
62 | */ | |
63 | static void SetActive(wxEventLoopBase* loop); | |
64 | ||
65 | /** | |
66 | Returns @true if this is the main loop executed by wxApp::OnRun(). | |
67 | */ | |
68 | bool IsMain() const; | |
69 | ||
70 | ||
71 | /** | |
72 | @name Dispatch and processing | |
73 | */ | |
74 | //@{ | |
75 | ||
76 | /** | |
77 | Start the event loop, return the exit code when it is finished. | |
78 | ||
79 | Logically, this method calls Dispatch() in a loop until it returns | |
80 | @false and also takes care of generating idle events during each loop | |
81 | iteration. However not all implementations of this class really | |
82 | implement it like this (e.g. wxGTK does not) so you shouldn't rely on | |
83 | Dispatch() being called from inside this function. | |
84 | ||
85 | @return The argument passed to Exit() which terminated this event loop. | |
86 | */ | |
87 | virtual int Run() = 0; | |
88 | ||
89 | /** | |
90 | Return true if this event loop is currently running. | |
91 | ||
92 | Notice that even if this event loop hasn't terminated yet but has just | |
93 | spawned a nested (e.g. modal) event loop, this method would return | |
94 | @false. | |
95 | */ | |
96 | bool IsRunning() const; | |
97 | ||
98 | /** | |
99 | Use this to check whether the event loop was successfully created | |
100 | before using it | |
101 | */ | |
102 | virtual bool IsOk() const; | |
103 | ||
104 | /** | |
105 | Exit the currently running loop with the given exit code. | |
106 | ||
107 | The loop will exit, i.e. its Run() method will return, during the next | |
108 | event loop iteration. | |
109 | ||
110 | Notice that this method can only be used if this event loop is the | |
111 | currently running one, i.e. its IsRunning() returns @true. If this is | |
112 | not the case, an assert failure is triggered and nothing is done as | |
113 | outer event loops can't be exited from immediately. Use ScheduleExit() | |
114 | if you'd like to exit this loop even if it doesn't run currently. | |
115 | */ | |
116 | virtual void Exit(int rc = 0); | |
117 | ||
118 | /** | |
119 | Schedule an exit from the loop with the given exit code. | |
120 | ||
121 | This method is similar to Exit() but can be called even if this event | |
122 | loop is not the currently running one -- and if it is the active loop, | |
123 | then it works in exactly the same way as Exit(). | |
124 | ||
125 | The loop will exit as soon as the control flow returns to it, i.e. | |
126 | after any nested loops terminate. | |
127 | ||
128 | @since 2.9.5 | |
129 | */ | |
130 | virtual void ScheduleExit(int rc = 0) = 0; | |
131 | ||
132 | /** | |
133 | Return true if any events are available. | |
134 | ||
135 | If this method returns @true, calling Dispatch() will not block. | |
136 | */ | |
137 | virtual bool Pending() const = 0; | |
138 | ||
139 | /** | |
140 | Dispatches the next event in the windowing system event queue. | |
141 | Blocks until an event appears if there are none currently | |
142 | (use Pending() if this is not wanted). | |
143 | ||
144 | This can be used for programming event loops, e.g. | |
145 | ||
146 | @code | |
147 | while (evtloop->Pending()) | |
148 | evtloop->Dispatch(); | |
149 | @endcode | |
150 | ||
151 | @return @false if the event loop should stop and @true otherwise. | |
152 | ||
153 | @see Pending(), wxEventLoopBase | |
154 | */ | |
155 | virtual bool Dispatch() = 0; | |
156 | ||
157 | /** | |
158 | Dispatch an event but not wait longer than the specified timeout for | |
159 | it. | |
160 | ||
161 | If an event is received before the specified @a timeout expires, it is | |
162 | processed and the function returns 1 normally or 0 if the event loop | |
163 | should quite. Otherwise, i.e. if the timeout expires, the functions | |
164 | returns -1 without processing any events. | |
165 | ||
166 | @param timeout | |
167 | The maximal time to wait for the events in milliseconds. | |
168 | ||
169 | @return | |
170 | 1 if an event was processed, 0 if the event loop should quit or -1 | |
171 | if the timeout expired. | |
172 | */ | |
173 | virtual int DispatchTimeout(unsigned long timeout) = 0; | |
174 | ||
175 | /** | |
176 | Called by wxWidgets to wake up the event loop even if it is currently | |
177 | blocked inside Dispatch(). | |
178 | */ | |
179 | virtual void WakeUp() = 0; | |
180 | ||
181 | //@} | |
182 | ||
183 | ||
184 | /** | |
185 | @name Idle handling | |
186 | */ | |
187 | //@{ | |
188 | ||
189 | /** | |
190 | Makes sure that idle events are sent again. | |
191 | */ | |
192 | virtual void WakeUpIdle(); | |
193 | ||
194 | /** | |
195 | This virtual function is called when the application becomes idle and | |
196 | normally just sends wxIdleEvent to all interested parties. | |
197 | ||
198 | It should return @true if more idle events are needed, @false if not. | |
199 | */ | |
200 | virtual bool ProcessIdle(); | |
201 | ||
202 | //@} | |
203 | ||
204 | ||
205 | /** | |
206 | @name Yield-related hooks | |
207 | */ | |
208 | //@{ | |
209 | ||
210 | /** | |
211 | Returns @true if called from inside Yield() or from inside YieldFor(). | |
212 | */ | |
213 | virtual bool IsYielding() const; | |
214 | ||
215 | /** | |
216 | Yields control to pending messages in the windowing system. | |
217 | ||
218 | This can be useful, for example, when a time-consuming process writes to a | |
219 | text window. Without an occasional yield, the text window will not be updated | |
220 | properly, and on systems with cooperative multitasking, such as Windows 3.1 | |
221 | other processes will not respond. | |
222 | ||
223 | Caution should be exercised, however, since yielding may allow the | |
224 | user to perform actions which are not compatible with the current task. | |
225 | Disabling menu items or whole menus during processing can avoid unwanted | |
226 | reentrance of code: see ::wxSafeYield for a better function. | |
227 | You can avoid unwanted reentrancies also using IsYielding(). | |
228 | ||
229 | Note that Yield() will not flush the message logs. This is intentional as | |
230 | calling Yield() is usually done to quickly update the screen and popping up | |
231 | a message box dialog may be undesirable. If you do wish to flush the log | |
232 | messages immediately (otherwise it will be done during the next idle loop | |
233 | iteration), call wxLog::FlushActive. | |
234 | ||
235 | Calling Yield() recursively is normally an error and an assert failure is | |
236 | raised in debug build if such situation is detected. However if the | |
237 | @a onlyIfNeeded parameter is @true, the method will just silently | |
238 | return @false instead. | |
239 | */ | |
240 | bool Yield(bool onlyIfNeeded = false); | |
241 | ||
242 | /** | |
243 | Works like Yield() with @e onlyIfNeeded == @true, except that it allows | |
244 | the caller to specify a mask of the ::wxEventCategory values which | |
245 | indicates which events should be processed and which should instead | |
246 | be "delayed" (i.e. processed by the main loop later). | |
247 | ||
248 | Note that this is a safer alternative to Yield() since it ensures that | |
249 | only the events you're interested to will be processed; i.e. this method | |
250 | helps to avoid unwanted reentrancies. | |
251 | ||
252 | Note that currently only wxMSW and wxGTK do support selective yield of | |
253 | native events coming from the underlying GUI toolkit. | |
254 | wxWidgets events posted using wxEvtHandler::AddPendingEvent or | |
255 | wxEvtHandler::QueueEvent are instead selectively processed by all ports. | |
256 | ||
257 | @see wxEvent::GetEventCategory | |
258 | */ | |
259 | bool YieldFor(long eventsToProcess); | |
260 | ||
261 | /** | |
262 | Returns @true if the given event category is allowed inside | |
263 | a YieldFor() call (i.e. compares the given category against the | |
264 | last mask passed to YieldFor()). | |
265 | ||
266 | @see wxEvent::GetEventCategory | |
267 | */ | |
268 | virtual bool IsEventAllowedInsideYield(wxEventCategory cat) const; | |
269 | ||
270 | //@} | |
271 | ||
272 | ||
273 | protected: | |
274 | /** | |
275 | This function is called before the event loop terminates, whether this | |
276 | happens normally (because of Exit() call) or abnormally (because of an | |
277 | exception thrown from inside the loop). | |
278 | ||
279 | The default implementation calls wxAppConsole::OnEventLoopExit. | |
280 | */ | |
281 | virtual void OnExit(); | |
282 | }; | |
283 | ||
284 | /** | |
285 | @class wxEventLoopActivator | |
286 | ||
287 | Makes an event loop temporarily active. | |
288 | ||
289 | This class is used to make the event loop active during its life-time, | |
290 | e.g.: | |
291 | @code | |
292 | class MyEventLoop : public wxEventLoopBase { ... }; | |
293 | ||
294 | void RunMyLoop() | |
295 | { | |
296 | MyEventLoop loop; | |
297 | wxEventLoopActivator activate(&loop); | |
298 | ||
299 | ... | |
300 | } // the previously active event loop restored here | |
301 | @endcode | |
302 | ||
303 | @library{wxbase} | |
304 | @category{appmanagement} | |
305 | ||
306 | @see wxEventLoopBase | |
307 | */ | |
308 | class wxEventLoopActivator | |
309 | { | |
310 | public: | |
311 | /** | |
312 | Makes the loop passed as the parameter currently active. | |
313 | ||
314 | This saves the current return value of wxEventLoopBase::GetActive() and | |
315 | then calls wxEventLoopBase::SetActive() with the given @a loop. | |
316 | */ | |
317 | wxEventLoopActivator(wxEventLoopBase *loop); | |
318 | ||
319 | /** | |
320 | Restores the previously active event loop stored by the constructor. | |
321 | */ | |
322 | ~wxEventLoopActivator(); | |
323 | }; | |
324 | ||
325 | /** | |
326 | @class wxGUIEventLoop | |
327 | ||
328 | A generic implementation of the GUI event loop. | |
329 | ||
330 | @library{wxbase} | |
331 | @category{appmanagement} | |
332 | */ | |
333 | class wxGUIEventLoop : public wxEventLoopBase | |
334 | { | |
335 | public: | |
336 | wxGUIEventLoop(); | |
337 | virtual ~wxGUIEventLoop(); | |
338 | }; | |
339 | ||
340 |