// Purpose: wxEventLoop and related classes
// Author: Vadim Zeitlin
// Copyright: (C) 2008 Vadim Zeitlin
-// RCS-ID: $Id$
-// Licence: wxWindows license
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
/**
Base class for all event loop implementations.
+ An event loop is a class which queries the queue of native events sent
+ to the wxWidgets application and dispatches them to the appropriate
+ wxEvtHandlers.
+
An object of this class is created by wxAppTraits::CreateEventLoop() and
used by wxApp to run the main application event loop.
+ Temporary event loops are usually created by wxDialog::ShowModal().
+
+ You can create your own event loop if you need, provided that you restore
+ the main event loop once yours is destroyed (see wxEventLoopActivator).
+
+ Notice that there can be more than one event loop at any given moment, e.g.
+ an event handler called from the main loop can show a modal dialog, which
+ starts its own loop resulting in two nested loops, with the modal dialog
+ being the active one (its IsRunning() returns @true). And a handler for a
+ button inside the modal dialog can, of course, create another modal dialog
+ with its own event loop and so on. So in general event loops form a stack
+ and only the event loop at the top of the stack is considered to be active.
+ It is also the only loop that can be directly asked to terminate by calling
+ Exit() (which is done by wxDialog::EndModal()), an outer event loop can't
+ be stopped while an inner one is still running. It is however possible to
+ ask an outer event loop to terminate as soon as all its nested loops exit
+ and the control returns back to it by using ScheduleExit().
@library{wxbase}
@category{appmanagement}
- @see wxApp
+ @see wxApp, wxEventLoopActivator
*/
class wxEventLoopBase
{
Called by wxEventLoopActivator, use an instance of this class instead
of calling this method directly to ensure that the previously active
event loop is restored.
+
+ Results in a call to wxAppConsole::OnEventLoopEnter.
*/
static void SetActive(wxEventLoopBase* loop);
+ /**
+ Returns @true if this is the main loop executed by wxApp::OnRun().
+ */
+ bool IsMain() const;
+
/**
- Use this to check whether the event loop was successfully created
- before using it
- */
- virtual bool IsOk() const;
+ @name Dispatch and processing
+ */
+ //@{
/**
Start the event loop, return the exit code when it is finished.
virtual int Run() = 0;
/**
- Exit from the loop with the given exit code.
+ Return true if this event loop is currently running.
+
+ Notice that even if this event loop hasn't terminated yet but has just
+ spawned a nested (e.g. modal) event loop, this method would return
+ @false.
+ */
+ bool IsRunning() const;
+
+ /**
+ Use this to check whether the event loop was successfully created
+ before using it
+ */
+ virtual bool IsOk() const;
+
+ /**
+ Exit the currently running loop with the given exit code.
+
+ The loop will exit, i.e. its Run() method will return, during the next
+ event loop iteration.
+
+ Notice that this method can only be used if this event loop is the
+ currently running one, i.e. its IsRunning() returns @true. If this is
+ not the case, an assert failure is triggered and nothing is done as
+ outer event loops can't be exited from immediately. Use ScheduleExit()
+ if you'd like to exit this loop even if it doesn't run currently.
+ */
+ virtual void Exit(int rc = 0);
+
+ /**
+ Schedule an exit from the loop with the given exit code.
+
+ This method is similar to Exit() but can be called even if this event
+ loop is not the currently running one -- and if it is the active loop,
+ then it works in exactly the same way as Exit().
+
+ The loop will exit as soon as the control flow returns to it, i.e.
+ after any nested loops terminate.
+
+ @since 2.9.5
*/
- virtual void Exit(int rc = 0) = 0;
+ virtual void ScheduleExit(int rc = 0) = 0;
/**
Return true if any events are available.
virtual bool Pending() const = 0;
/**
- Dispatch a single event.
+ Dispatches the next event in the windowing system event queue.
+ Blocks until an event appears if there are none currently
+ (use Pending() if this is not wanted).
- If there are currently no events in the queue, blocks until an event
- becomes available.
+ This can be used for programming event loops, e.g.
- @return @false only if the event loop should terminate.
- */
+ @code
+ while (evtloop->Pending())
+ evtloop->Dispatch();
+ @endcode
+
+ @return @false if the event loop should stop and @true otherwise.
+
+ @see Pending(), wxEventLoopBase
+ */
virtual bool Dispatch() = 0;
/**
- Return true if this event loop is currently running.
+ Dispatch an event but not wait longer than the specified timeout for
+ it.
- Notice that even if this event loop hasn't terminated yet but has just
- spawned a nested (e.g. modal) event loop, this method would return
- @false.
+ If an event is received before the specified @a timeout expires, it is
+ processed and the function returns 1 normally or 0 if the event loop
+ should quite. Otherwise, i.e. if the timeout expires, the functions
+ returns -1 without processing any events.
+
+ @param timeout
+ The maximal time to wait for the events in milliseconds.
+
+ @return
+ 1 if an event was processed, 0 if the event loop should quit or -1
+ if the timeout expired.
*/
- bool IsRunning() const;
+ virtual int DispatchTimeout(unsigned long timeout) = 0;
/**
Called by wxWidgets to wake up the event loop even if it is currently
*/
virtual void WakeUp() = 0;
+ //@}
+
+
+ /**
+ @name Idle handling
+ */
+ //@{
+
+ /**
+ Makes sure that idle events are sent again.
+ */
+ virtual void WakeUpIdle();
+
+ /**
+ This virtual function is called when the application becomes idle and
+ normally just sends wxIdleEvent to all interested parties.
+
+ It should return @true if more idle events are needed, @false if not.
+ */
+ virtual bool ProcessIdle();
+
+ //@}
+
+
+ /**
+ @name Yield-related hooks
+ */
+ //@{
+
+ /**
+ Returns @true if called from inside Yield() or from inside YieldFor().
+ */
+ virtual bool IsYielding() const;
+
+ /**
+ Yields control to pending messages in the windowing system.
+
+ This can be useful, for example, when a time-consuming process writes to a
+ text window. Without an occasional yield, the text window will not be updated
+ properly, and on systems with cooperative multitasking, such as Windows 3.1
+ other processes will not respond.
+
+ Caution should be exercised, however, since yielding may allow the
+ user to perform actions which are not compatible with the current task.
+ Disabling menu items or whole menus during processing can avoid unwanted
+ reentrance of code: see ::wxSafeYield for a better function.
+ You can avoid unwanted reentrancies also using IsYielding().
+
+ Note that Yield() will not flush the message logs. This is intentional as
+ calling Yield() is usually done to quickly update the screen and popping up
+ a message box dialog may be undesirable. If you do wish to flush the log
+ messages immediately (otherwise it will be done during the next idle loop
+ iteration), call wxLog::FlushActive.
+
+ Calling Yield() recursively is normally an error and an assert failure is
+ raised in debug build if such situation is detected. However if the
+ @a onlyIfNeeded parameter is @true, the method will just silently
+ return @false instead.
+ */
+ bool Yield(bool onlyIfNeeded = false);
+
+ /**
+ Works like Yield() with @e onlyIfNeeded == @true, except that it allows
+ the caller to specify a mask of the ::wxEventCategory values which
+ indicates which events should be processed and which should instead
+ be "delayed" (i.e. processed by the main loop later).
+
+ Note that this is a safer alternative to Yield() since it ensures that
+ only the events you're interested to will be processed; i.e. this method
+ helps to avoid unwanted reentrancies.
+
+ Note that currently only wxMSW and wxGTK do support selective yield of
+ native events coming from the underlying GUI toolkit.
+ wxWidgets events posted using wxEvtHandler::AddPendingEvent or
+ wxEvtHandler::QueueEvent are instead selectively processed by all ports.
+
+ @see wxEvent::GetEventCategory
+ */
+ bool YieldFor(long eventsToProcess);
+
+ /**
+ Returns @true if the given event category is allowed inside
+ a YieldFor() call (i.e. compares the given category against the
+ last mask passed to YieldFor()).
+
+ @see wxEvent::GetEventCategory
+ */
+ virtual bool IsEventAllowedInsideYield(wxEventCategory cat) const;
+
+ //@}
+
+
protected:
/**
This function is called before the event loop terminates, whether this
happens normally (because of Exit() call) or abnormally (because of an
exception thrown from inside the loop).
- Default version does nothing.
+ The default implementation calls wxAppConsole::OnEventLoopExit.
*/
virtual void OnExit();
};
*/
~wxEventLoopActivator();
};
+
+/**
+ @class wxGUIEventLoop
+
+ A generic implementation of the GUI event loop.
+
+ @library{wxbase}
+ @category{appmanagement}
+*/
+class wxGUIEventLoop : public wxEventLoopBase
+{
+public:
+ wxGUIEventLoop();
+ virtual ~wxGUIEventLoop();
+};
+
+