PageRenderTime 55ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/Externals/wxWidgets3/include/wx/evtloop.h

https://gitlab.com/WoomyNightClub/dolphin
C Header | 435 lines | 189 code | 88 blank | 158 comment | 17 complexity | 22ca826226f297ac7a0a14bcde2e255c MD5 | raw file
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name: wx/evtloop.h
  3. // Purpose: declares wxEventLoop class
  4. // Author: Vadim Zeitlin
  5. // Modified by:
  6. // Created: 01.06.01
  7. // Copyright: (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
  8. // Licence: wxWindows licence
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #ifndef _WX_EVTLOOP_H_
  11. #define _WX_EVTLOOP_H_
  12. #include "wx/event.h"
  13. #include "wx/utils.h"
  14. // TODO: implement wxEventLoopSource for MSW (it should wrap a HANDLE and be
  15. // monitored using MsgWaitForMultipleObjects())
  16. #if defined(__WXOSX__) || (defined(__UNIX__) && !defined(__WXMSW__))
  17. #define wxUSE_EVENTLOOP_SOURCE 1
  18. #else
  19. #define wxUSE_EVENTLOOP_SOURCE 0
  20. #endif
  21. #if wxUSE_EVENTLOOP_SOURCE
  22. class wxEventLoopSource;
  23. class wxEventLoopSourceHandler;
  24. #endif
  25. /*
  26. NOTE ABOUT wxEventLoopBase::YieldFor LOGIC
  27. ------------------------------------------
  28. The YieldFor() function helps to avoid re-entrancy problems and problems
  29. caused by out-of-order event processing
  30. (see "wxYield-like problems" and "wxProgressDialog+threading BUG" wx-dev threads).
  31. The logic behind YieldFor() is simple: it analyzes the queue of the native
  32. events generated by the underlying GUI toolkit and picks out and processes
  33. only those matching the given mask.
  34. It's important to note that YieldFor() is used to selectively process the
  35. events generated by the NATIVE toolkit.
  36. Events syntethized by wxWidgets code or by user code are instead selectively
  37. processed thanks to the logic built into wxEvtHandler::ProcessPendingEvents().
  38. In fact, when wxEvtHandler::ProcessPendingEvents gets called from inside a
  39. YieldFor() call, wxEventLoopBase::IsEventAllowedInsideYield is used to decide
  40. if the pending events for that event handler can be processed.
  41. If all the pending events associated with that event handler result as "not processable",
  42. the event handler "delays" itself calling wxEventLoopBase::DelayPendingEventHandler
  43. (so it's moved: m_handlersWithPendingEvents => m_handlersWithPendingDelayedEvents).
  44. Last, wxEventLoopBase::ProcessPendingEvents() before exiting moves the delayed
  45. event handlers back into the list of handlers with pending events
  46. (m_handlersWithPendingDelayedEvents => m_handlersWithPendingEvents) so that
  47. a later call to ProcessPendingEvents() (possibly outside the YieldFor() call)
  48. will process all pending events as usual.
  49. */
  50. // ----------------------------------------------------------------------------
  51. // wxEventLoopBase: interface for wxEventLoop
  52. // ----------------------------------------------------------------------------
  53. class WXDLLIMPEXP_BASE wxEventLoopBase
  54. {
  55. public:
  56. // trivial, but needed (because of wxEventLoopBase) ctor
  57. wxEventLoopBase();
  58. // dtor
  59. virtual ~wxEventLoopBase() { }
  60. // use this to check whether the event loop was successfully created before
  61. // using it
  62. virtual bool IsOk() const { return true; }
  63. // returns true if this is the main loop
  64. bool IsMain() const;
  65. #if wxUSE_EVENTLOOP_SOURCE
  66. // create a new event loop source wrapping the given file descriptor and
  67. // monitor it for events occurring on this descriptor in all event loops
  68. static wxEventLoopSource *
  69. AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags);
  70. #endif // wxUSE_EVENTLOOP_SOURCE
  71. // dispatch&processing
  72. // -------------------
  73. // start the event loop, return the exit code when it is finished
  74. //
  75. // notice that wx ports should override DoRun(), this method is virtual
  76. // only to allow overriding it in the user code for custom event loops
  77. virtual int Run();
  78. // is this event loop running now?
  79. //
  80. // notice that even if this event loop hasn't terminated yet but has just
  81. // spawned a nested (e.g. modal) event loop, this would return false
  82. bool IsRunning() const;
  83. // exit from the loop with the given exit code
  84. //
  85. // this can be only used to exit the currently running loop, use
  86. // ScheduleExit() if this might not be the case
  87. virtual void Exit(int rc = 0);
  88. // ask the event loop to exit with the given exit code, can be used even if
  89. // this loop is not running right now but the loop must have been started,
  90. // i.e. Run() should have been already called
  91. virtual void ScheduleExit(int rc = 0) = 0;
  92. // return true if any events are available
  93. virtual bool Pending() const = 0;
  94. // dispatch a single event, return false if we should exit from the loop
  95. virtual bool Dispatch() = 0;
  96. // same as Dispatch() but doesn't wait for longer than the specified (in
  97. // ms) timeout, return true if an event was processed, false if we should
  98. // exit the loop or -1 if timeout expired
  99. virtual int DispatchTimeout(unsigned long timeout) = 0;
  100. // implement this to wake up the loop: usually done by posting a dummy event
  101. // to it (can be called from non main thread)
  102. virtual void WakeUp() = 0;
  103. // idle handling
  104. // -------------
  105. // make sure that idle events are sent again
  106. virtual void WakeUpIdle();
  107. // this virtual function is called when the application
  108. // becomes idle and by default it forwards to wxApp::ProcessIdle() and
  109. // while it can be overridden in a custom event loop, you must call the
  110. // base class version to ensure that idle events are still generated
  111. //
  112. // it should return true if more idle events are needed, false if not
  113. virtual bool ProcessIdle();
  114. // Yield-related hooks
  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. // returns true if the main thread is inside a Yield() call
  128. virtual bool IsYielding() const
  129. { return m_isInsideYield; }
  130. // returns true if events of the given event category should be immediately
  131. // processed inside a wxApp::Yield() call or rather should be queued for
  132. // later processing by the main event loop
  133. virtual bool IsEventAllowedInsideYield(wxEventCategory cat) const
  134. { return (m_eventsToProcessInsideYield & cat) != 0; }
  135. // no SafeYield hooks since it uses wxWindow which is not available when wxUSE_GUI=0
  136. // active loop
  137. // -----------
  138. // return currently active (running) event loop, may be NULL
  139. static wxEventLoopBase *GetActive() { return ms_activeLoop; }
  140. // set currently active (running) event loop
  141. static void SetActive(wxEventLoopBase* loop);
  142. protected:
  143. // real implementation of Run()
  144. virtual int DoRun() = 0;
  145. // this function should be called before the event loop terminates, whether
  146. // this happens normally (because of Exit() call) or abnormally (because of
  147. // an exception thrown from inside the loop)
  148. virtual void OnExit();
  149. // Return true if we're currently inside our Run(), even if another nested
  150. // event loop is currently running, unlike IsRunning() (which should have
  151. // been really called IsActive() but it's too late to change this now).
  152. bool IsInsideRun() const { return m_isInsideRun; }
  153. // the pointer to currently active loop
  154. static wxEventLoopBase *ms_activeLoop;
  155. // should we exit the loop?
  156. bool m_shouldExit;
  157. // YieldFor() helpers:
  158. bool m_isInsideYield;
  159. long m_eventsToProcessInsideYield;
  160. private:
  161. // this flag is set on entry into Run() and reset before leaving it
  162. bool m_isInsideRun;
  163. wxDECLARE_NO_COPY_CLASS(wxEventLoopBase);
  164. };
  165. #if defined(__WINDOWS__) || defined(__WXMAC__) || defined(__WXDFB__) || (defined(__UNIX__) && !defined(__WXOSX__))
  166. // this class can be used to implement a standard event loop logic using
  167. // Pending() and Dispatch()
  168. //
  169. // it also handles idle processing automatically
  170. class WXDLLIMPEXP_BASE wxEventLoopManual : public wxEventLoopBase
  171. {
  172. public:
  173. wxEventLoopManual();
  174. // sets the "should exit" flag and wakes up the loop so that it terminates
  175. // soon
  176. virtual void ScheduleExit(int rc = 0);
  177. protected:
  178. // enters a loop calling OnNextIteration(), Pending() and Dispatch() and
  179. // terminating when Exit() is called
  180. virtual int DoRun();
  181. // may be overridden to perform some action at the start of each new event
  182. // loop iteration
  183. virtual void OnNextIteration() { }
  184. // the loop exit code
  185. int m_exitcode;
  186. private:
  187. // process all already pending events and dispatch a new one (blocking
  188. // until it appears in the event queue if necessary)
  189. //
  190. // returns the return value of Dispatch()
  191. bool ProcessEvents();
  192. wxDECLARE_NO_COPY_CLASS(wxEventLoopManual);
  193. };
  194. #endif // platforms using "manual" loop
  195. // we're moving away from old m_impl wxEventLoop model as otherwise the user
  196. // code doesn't have access to platform-specific wxEventLoop methods and this
  197. // can sometimes be very useful (e.g. under MSW this is necessary for
  198. // integration with MFC) but currently this is not done for all ports yet (e.g.
  199. // wxX11) so fall back to the old wxGUIEventLoop definition below for them
  200. #if defined(__DARWIN__)
  201. // CoreFoundation-based event loop is currently in wxBase so include it in
  202. // any case too (although maybe it actually shouldn't be there at all)
  203. #include "wx/osx/core/evtloop.h"
  204. #endif
  205. // include the header defining wxConsoleEventLoop
  206. #if defined(__UNIX__) && !defined(__WXMSW__)
  207. #include "wx/unix/evtloop.h"
  208. #elif defined(__WINDOWS__)
  209. #include "wx/msw/evtloopconsole.h"
  210. #endif
  211. #if wxUSE_GUI
  212. // include the appropriate header defining wxGUIEventLoop
  213. #if defined(__WXMSW__)
  214. #include "wx/msw/evtloop.h"
  215. #elif defined(__WXCOCOA__)
  216. #include "wx/cocoa/evtloop.h"
  217. #elif defined(__WXOSX__)
  218. #include "wx/osx/evtloop.h"
  219. #elif defined(__WXDFB__)
  220. #include "wx/dfb/evtloop.h"
  221. #elif defined(__WXGTK20__)
  222. #include "wx/gtk/evtloop.h"
  223. #else // other platform
  224. #include "wx/stopwatch.h" // for wxMilliClock_t
  225. class WXDLLIMPEXP_FWD_CORE wxEventLoopImpl;
  226. class WXDLLIMPEXP_CORE wxGUIEventLoop : public wxEventLoopBase
  227. {
  228. public:
  229. wxGUIEventLoop() { m_impl = NULL; }
  230. virtual ~wxGUIEventLoop();
  231. virtual void ScheduleExit(int rc = 0);
  232. virtual bool Pending() const;
  233. virtual bool Dispatch();
  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. if ( wxGetLocalTimeMillis() >= timeEnd )
  244. return -1;
  245. }
  246. }
  247. virtual void WakeUp() { }
  248. virtual bool YieldFor(long eventsToProcess);
  249. protected:
  250. virtual int DoRun();
  251. // the pointer to the port specific implementation class
  252. wxEventLoopImpl *m_impl;
  253. wxDECLARE_NO_COPY_CLASS(wxGUIEventLoop);
  254. };
  255. #endif // platforms
  256. #endif // wxUSE_GUI
  257. #if wxUSE_GUI
  258. // we use a class rather than a typedef because wxEventLoop is
  259. // forward-declared in many places
  260. class wxEventLoop : public wxGUIEventLoop { };
  261. #else // !wxUSE_GUI
  262. // we can't define wxEventLoop differently in GUI and base libraries so use
  263. // a #define to still allow writing wxEventLoop in the user code
  264. #if wxUSE_CONSOLE_EVENTLOOP && (defined(__WINDOWS__) || defined(__UNIX__))
  265. #define wxEventLoop wxConsoleEventLoop
  266. #else // we still must define it somehow for the code below...
  267. #define wxEventLoop wxEventLoopBase
  268. #endif
  269. #endif
  270. inline bool wxEventLoopBase::IsRunning() const { return GetActive() == this; }
  271. #if wxUSE_GUI && !defined(__WXOSX__)
  272. // ----------------------------------------------------------------------------
  273. // wxModalEventLoop
  274. // ----------------------------------------------------------------------------
  275. // this is a naive generic implementation which uses wxWindowDisabler to
  276. // implement modality, we will surely need platform-specific implementations
  277. // too, this generic implementation is here only temporarily to see how it
  278. // works
  279. class WXDLLIMPEXP_CORE wxModalEventLoop : public wxGUIEventLoop
  280. {
  281. public:
  282. wxModalEventLoop(wxWindow *winModal)
  283. {
  284. m_windowDisabler = new wxWindowDisabler(winModal);
  285. }
  286. protected:
  287. virtual void OnExit()
  288. {
  289. delete m_windowDisabler;
  290. m_windowDisabler = NULL;
  291. wxGUIEventLoop::OnExit();
  292. }
  293. private:
  294. wxWindowDisabler *m_windowDisabler;
  295. };
  296. #endif //wxUSE_GUI
  297. // ----------------------------------------------------------------------------
  298. // wxEventLoopActivator: helper class for wxEventLoop implementations
  299. // ----------------------------------------------------------------------------
  300. // this object sets the wxEventLoop given to the ctor as the currently active
  301. // one and unsets it in its dtor, this is especially useful in presence of
  302. // exceptions but is more tidy even when we don't use them
  303. class wxEventLoopActivator
  304. {
  305. public:
  306. wxEventLoopActivator(wxEventLoopBase *evtLoop)
  307. {
  308. m_evtLoopOld = wxEventLoopBase::GetActive();
  309. wxEventLoopBase::SetActive(evtLoop);
  310. }
  311. ~wxEventLoopActivator()
  312. {
  313. // restore the previously active event loop
  314. wxEventLoopBase::SetActive(m_evtLoopOld);
  315. }
  316. private:
  317. wxEventLoopBase *m_evtLoopOld;
  318. };
  319. #if wxUSE_CONSOLE_EVENTLOOP
  320. class wxEventLoopGuarantor
  321. {
  322. public:
  323. wxEventLoopGuarantor()
  324. {
  325. m_evtLoopNew = NULL;
  326. if (!wxEventLoop::GetActive())
  327. {
  328. m_evtLoopNew = new wxEventLoop;
  329. wxEventLoop::SetActive(m_evtLoopNew);
  330. }
  331. }
  332. ~wxEventLoopGuarantor()
  333. {
  334. if (m_evtLoopNew)
  335. {
  336. wxEventLoop::SetActive(NULL);
  337. delete m_evtLoopNew;
  338. }
  339. }
  340. private:
  341. wxEventLoop *m_evtLoopNew;
  342. };
  343. #endif // wxUSE_CONSOLE_EVENTLOOP
  344. #endif // _WX_EVTLOOP_H_