| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- /////////////////////////////////////////////////////////////////////////////
- // Name: wx/evtloop.h
- // Purpose: wxEventLoop and related classes
- // Author: Vadim Zeitlin
- // Copyright: (C) 2008 Vadim Zeitlin
- // Licence: wxWindows licence
- /////////////////////////////////////////////////////////////////////////////
- /**
- @class wxEventLoopBase
- 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, wxEventLoopActivator
- */
- class wxEventLoopBase
- {
- public:
- /**
- Return the currently active (running) event loop.
- May return @NULL if there is no active event loop (e.g. during
- application startup or shutdown).
- */
- static wxEventLoopBase *GetActive();
- /**
- Set currently active (running) event loop.
- 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;
- /**
- @name Dispatch and processing
- */
- //@{
- /**
- Start the event loop, return the exit code when it is finished.
- Logically, this method calls Dispatch() in a loop until it returns
- @false and also takes care of generating idle events during each loop
- iteration. However not all implementations of this class really
- implement it like this (e.g. wxGTK does not) so you shouldn't rely on
- Dispatch() being called from inside this function.
- @return The argument passed to Exit() which terminated this event loop.
- */
- virtual int Run() = 0;
- /**
- 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 ScheduleExit(int rc = 0) = 0;
- /**
- Return true if any events are available.
- If this method returns @true, calling Dispatch() will not block.
- */
- virtual bool Pending() const = 0;
- /**
- 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).
- This can be used for programming event loops, e.g.
- @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;
- /**
- Dispatch an event but not wait longer than the specified timeout for
- it.
- 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.
- */
- virtual int DispatchTimeout(unsigned long timeout) = 0;
- /**
- Called by wxWidgets to wake up the event loop even if it is currently
- blocked inside Dispatch().
- */
- 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).
- The default implementation calls wxAppConsole::OnEventLoopExit.
- */
- virtual void OnExit();
- };
- /**
- @class wxEventLoopActivator
- Makes an event loop temporarily active.
- This class is used to make the event loop active during its life-time,
- e.g.:
- @code
- class MyEventLoop : public wxEventLoopBase { ... };
- void RunMyLoop()
- {
- MyEventLoop loop;
- wxEventLoopActivator activate(&loop);
- ...
- } // the previously active event loop restored here
- @endcode
- @library{wxbase}
- @category{appmanagement}
- @see wxEventLoopBase
- */
- class wxEventLoopActivator
- {
- public:
- /**
- Makes the loop passed as the parameter currently active.
- This saves the current return value of wxEventLoopBase::GetActive() and
- then calls wxEventLoopBase::SetActive() with the given @a loop.
- */
- wxEventLoopActivator(wxEventLoopBase *loop);
- /**
- Restores the previously active event loop stored by the constructor.
- */
- ~wxEventLoopActivator();
- };
- /**
- @class wxGUIEventLoop
- A generic implementation of the GUI event loop.
-
- @library{wxbase}
- @category{appmanagement}
- */
- class wxGUIEventLoop : public wxEventLoopBase
- {
- public:
- wxGUIEventLoop();
- virtual ~wxGUIEventLoop();
- };
|