2001-06-29 13:21:17 -04:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Name: wx/evtloop.h
|
|
|
|
// Purpose: declares wxEventLoop class
|
|
|
|
// Author: Vadim Zeitlin
|
|
|
|
// Modified by:
|
|
|
|
// Created: 01.06.01
|
|
|
|
// RCS-ID: $Id$
|
|
|
|
// Copyright: (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
|
2004-05-23 16:53:33 -04:00
|
|
|
// Licence: wxWindows licence
|
2001-06-29 13:21:17 -04:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#ifndef _WX_EVTLOOP_H_
|
|
|
|
#define _WX_EVTLOOP_H_
|
|
|
|
|
2009-02-16 12:19:17 -05:00
|
|
|
#include "wx/event.h"
|
2003-09-18 06:01:59 -04:00
|
|
|
#include "wx/utils.h"
|
|
|
|
|
2009-02-15 09:25:08 -05:00
|
|
|
/*
|
|
|
|
NOTE ABOUT wxEventLoopBase::YieldFor LOGIC
|
|
|
|
------------------------------------------
|
|
|
|
|
|
|
|
The YieldFor() function helps to avoid re-entrancy problems and problems
|
|
|
|
caused by out-of-order event processing
|
|
|
|
(see "wxYield-like problems" and "wxProgressDialog+threading BUG" wx-dev threads).
|
|
|
|
|
|
|
|
The logic behind YieldFor() is simple: it analyzes the queue of the native
|
|
|
|
events generated by the underlying GUI toolkit and picks out and processes
|
|
|
|
only those matching the given mask.
|
|
|
|
|
|
|
|
It's important to note that YieldFor() is used to selectively process the
|
|
|
|
events generated by the NATIVE toolkit.
|
|
|
|
Events syntethized by wxWidgets code or by user code are instead selectively
|
|
|
|
processed thanks to the logic built into wxEvtHandler::ProcessPendingEvents().
|
|
|
|
In fact, when wxEvtHandler::ProcessPendingEvents gets called from inside a
|
|
|
|
YieldFor() call, wxEventLoopBase::IsEventAllowedInsideYield is used to decide
|
|
|
|
if the pending events for that event handler can be processed.
|
|
|
|
If all the pending events associated with that event handler result as "not processable",
|
|
|
|
the event handler "delays" itself calling wxEventLoopBase::DelayPendingEventHandler
|
|
|
|
(so it's moved: m_handlersWithPendingEvents => m_handlersWithPendingDelayedEvents).
|
|
|
|
Last, wxEventLoopBase::ProcessPendingEvents() before exiting moves the delayed
|
|
|
|
event handlers back into the list of handlers with pending events
|
|
|
|
(m_handlersWithPendingDelayedEvents => m_handlersWithPendingEvents) so that
|
|
|
|
a later call to ProcessPendingEvents() (possibly outside the YieldFor() call)
|
|
|
|
will process all pending events as usual.
|
|
|
|
*/
|
|
|
|
|
2001-06-29 13:21:17 -04:00
|
|
|
// ----------------------------------------------------------------------------
|
2007-05-14 19:43:39 -04:00
|
|
|
// wxEventLoopBase: interface for wxEventLoop
|
2001-06-29 13:21:17 -04:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
2007-05-14 19:43:39 -04:00
|
|
|
class WXDLLIMPEXP_BASE wxEventLoopBase
|
2001-06-29 13:21:17 -04:00
|
|
|
{
|
|
|
|
public:
|
2004-07-30 18:54:31 -04:00
|
|
|
// trivial, but needed (because of wxEventLoopBase) ctor
|
2009-02-15 09:25:08 -05:00
|
|
|
wxEventLoopBase();
|
2001-06-29 13:21:17 -04:00
|
|
|
|
|
|
|
// dtor
|
2004-07-30 18:54:31 -04:00
|
|
|
virtual ~wxEventLoopBase() { }
|
2001-06-29 13:21:17 -04:00
|
|
|
|
2007-05-14 19:43:39 -04:00
|
|
|
// use this to check whether the event loop was successfully created before
|
|
|
|
// using it
|
|
|
|
virtual bool IsOk() const { return true; }
|
|
|
|
|
2009-02-25 08:23:12 -05:00
|
|
|
// returns true if this is the main loop
|
|
|
|
bool IsMain() const;
|
|
|
|
|
2008-12-26 17:28:34 -05:00
|
|
|
|
2009-02-15 09:25:08 -05:00
|
|
|
// dispatch&processing
|
|
|
|
// -------------------
|
|
|
|
|
2001-06-29 13:21:17 -04:00
|
|
|
// start the event loop, return the exit code when it is finished
|
2004-07-30 18:54:31 -04:00
|
|
|
virtual int Run() = 0;
|
2001-06-29 13:21:17 -04:00
|
|
|
|
2009-02-15 09:25:08 -05:00
|
|
|
// is this event loop running now?
|
|
|
|
//
|
|
|
|
// notice that even if this event loop hasn't terminated yet but has just
|
|
|
|
// spawned a nested (e.g. modal) event loop, this would return false
|
|
|
|
bool IsRunning() const;
|
|
|
|
|
2001-06-29 13:21:17 -04:00
|
|
|
// exit from the loop with the given exit code
|
2004-07-30 18:54:31 -04:00
|
|
|
virtual void Exit(int rc = 0) = 0;
|
2001-06-29 13:21:17 -04:00
|
|
|
|
2004-09-13 14:03:44 -04:00
|
|
|
// return true if any events are available
|
2004-07-30 18:54:31 -04:00
|
|
|
virtual bool Pending() const = 0;
|
2001-06-29 13:21:17 -04:00
|
|
|
|
2004-09-13 14:03:44 -04:00
|
|
|
// dispatch a single event, return false if we should exit from the loop
|
2004-07-30 18:54:31 -04:00
|
|
|
virtual bool Dispatch() = 0;
|
2001-06-29 13:21:17 -04:00
|
|
|
|
2008-12-26 17:28:34 -05:00
|
|
|
// same as Dispatch() but doesn't wait for longer than the specified (in
|
|
|
|
// ms) timeout, return true if an event was processed, false if we should
|
|
|
|
// exit the loop or -1 if timeout expired
|
|
|
|
virtual int DispatchTimeout(unsigned long timeout) = 0;
|
|
|
|
|
2009-02-15 09:25:08 -05:00
|
|
|
// implement this to wake up the loop: usually done by posting a dummy event
|
|
|
|
// to it (can be called from non main thread)
|
|
|
|
virtual void WakeUp() = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// idle handling
|
|
|
|
// -------------
|
|
|
|
|
|
|
|
// make 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();
|
|
|
|
|
|
|
|
|
|
|
|
// Yield-related hooks
|
|
|
|
// -------------------
|
|
|
|
|
|
|
|
// process all currently pending events right now
|
|
|
|
//
|
|
|
|
// it is an error to call Yield() recursively unless the value of
|
|
|
|
// onlyIfNeeded is true
|
|
|
|
//
|
|
|
|
// WARNING: this function is dangerous as it can lead to unexpected
|
|
|
|
// reentrancies (i.e. when called from an event handler it
|
|
|
|
// may result in calling the same event handler again), use
|
|
|
|
// with _extreme_ care or, better, don't use at all!
|
|
|
|
bool Yield(bool onlyIfNeeded = false);
|
|
|
|
virtual bool YieldFor(long eventsToProcess) = 0;
|
|
|
|
|
|
|
|
// returns true if the main thread is inside a Yield() call
|
|
|
|
virtual bool IsYielding() const
|
|
|
|
{ return m_isInsideYield; }
|
|
|
|
|
|
|
|
// returns true if events of the given event category should be immediately
|
|
|
|
// processed inside a wxApp::Yield() call or rather should be queued for
|
|
|
|
// later processing by the main event loop
|
|
|
|
virtual bool IsEventAllowedInsideYield(wxEventCategory cat) const
|
|
|
|
{ return (m_eventsToProcessInsideYield & cat) != 0; }
|
|
|
|
|
|
|
|
// no SafeYield hooks since it uses wxWindow which is not available when wxUSE_GUI=0
|
|
|
|
|
|
|
|
|
|
|
|
// active loop
|
|
|
|
// -----------
|
2008-12-26 17:28:34 -05:00
|
|
|
|
2001-08-12 18:10:20 -04:00
|
|
|
// return currently active (running) event loop, may be NULL
|
2007-05-21 22:30:01 -04:00
|
|
|
static wxEventLoopBase *GetActive() { return ms_activeLoop; }
|
2001-06-29 13:21:17 -04:00
|
|
|
|
2002-03-24 16:19:27 -05:00
|
|
|
// set currently active (running) event loop
|
2009-02-25 08:23:12 -05:00
|
|
|
static void SetActive(wxEventLoopBase* loop);
|
2002-03-24 16:19:27 -05:00
|
|
|
|
2007-05-14 19:43:39 -04:00
|
|
|
|
2001-06-29 13:21:17 -04:00
|
|
|
protected:
|
2003-09-17 19:32:32 -04:00
|
|
|
// this function should be 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)
|
2009-02-25 08:23:12 -05:00
|
|
|
virtual void OnExit();
|
2003-09-17 19:32:32 -04:00
|
|
|
|
2001-08-12 18:10:20 -04:00
|
|
|
// the pointer to currently active loop
|
2007-05-21 22:30:01 -04:00
|
|
|
static wxEventLoopBase *ms_activeLoop;
|
2003-01-02 18:38:11 -05:00
|
|
|
|
2009-03-02 15:45:22 -05:00
|
|
|
// YieldFor() helpers:
|
2009-02-15 09:25:08 -05:00
|
|
|
bool m_isInsideYield;
|
|
|
|
long m_eventsToProcessInsideYield;
|
|
|
|
|
2009-02-08 06:45:59 -05:00
|
|
|
wxDECLARE_NO_COPY_CLASS(wxEventLoopBase);
|
2004-07-30 18:54:31 -04:00
|
|
|
};
|
|
|
|
|
2007-05-14 19:43:39 -04:00
|
|
|
#if defined(__WXMSW__) || defined(__WXMAC__) || defined(__WXDFB__) || defined(__UNIX__)
|
2006-01-12 18:06:26 -05:00
|
|
|
|
|
|
|
// this class can be used to implement a standard event loop logic using
|
|
|
|
// Pending() and Dispatch()
|
|
|
|
//
|
|
|
|
// it also handles idle processing automatically
|
2007-05-14 19:43:39 -04:00
|
|
|
class WXDLLIMPEXP_BASE wxEventLoopManual : public wxEventLoopBase
|
2006-01-12 18:06:26 -05:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
wxEventLoopManual();
|
|
|
|
|
|
|
|
// enters a loop calling OnNextIteration(), Pending() and Dispatch() and
|
|
|
|
// terminating when Exit() is called
|
|
|
|
virtual int Run();
|
|
|
|
|
|
|
|
// sets the "should exit" flag and wakes up the loop so that it terminates
|
|
|
|
// soon
|
2006-01-12 20:32:38 -05:00
|
|
|
virtual void Exit(int rc = 0);
|
2006-01-12 18:06:26 -05:00
|
|
|
|
|
|
|
protected:
|
|
|
|
// may be overridden to perform some action at the start of each new event
|
|
|
|
// loop iteration
|
|
|
|
virtual void OnNextIteration() { }
|
|
|
|
|
|
|
|
|
|
|
|
// the loop exit code
|
|
|
|
int m_exitcode;
|
|
|
|
|
|
|
|
// should we exit the loop?
|
|
|
|
bool m_shouldExit;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // platforms using "manual" loop
|
|
|
|
|
2004-07-30 18:54:31 -04:00
|
|
|
// we're moving away from old m_impl wxEventLoop model as otherwise the user
|
|
|
|
// code doesn't have access to platform-specific wxEventLoop methods and this
|
|
|
|
// can sometimes be very useful (e.g. under MSW this is necessary for
|
|
|
|
// integration with MFC) but currently this is done for MSW only, other ports
|
|
|
|
// should follow a.s.a.p.
|
2004-12-20 07:44:22 -05:00
|
|
|
#if defined(__WXPALMOS__)
|
2004-10-19 09:40:30 -04:00
|
|
|
#include "wx/palmos/evtloop.h"
|
|
|
|
#elif defined(__WXMSW__)
|
2004-07-30 18:54:31 -04:00
|
|
|
#include "wx/msw/evtloop.h"
|
2006-01-12 15:09:00 -05:00
|
|
|
#elif defined(__WXMAC__)
|
2008-06-11 15:17:41 -04:00
|
|
|
#include "wx/osx/evtloop.h"
|
2008-12-28 09:25:00 -05:00
|
|
|
#elif defined(__WXCOCOA__)
|
|
|
|
#include "wx/cocoa/evtloop.h"
|
2006-08-27 05:42:42 -04:00
|
|
|
#elif defined(__WXDFB__)
|
|
|
|
#include "wx/dfb/evtloop.h"
|
2008-12-27 06:01:39 -05:00
|
|
|
#elif defined(__WXGTK20__)
|
|
|
|
#include "wx/gtk/evtloop.h"
|
2006-01-12 15:09:00 -05:00
|
|
|
#else // other platform
|
2004-07-30 18:54:31 -04:00
|
|
|
|
2008-12-26 19:04:57 -05:00
|
|
|
#include "wx/stopwatch.h" // for wxMilliClock_t
|
2008-12-26 17:28:34 -05:00
|
|
|
|
2007-07-09 06:09:52 -04:00
|
|
|
class WXDLLIMPEXP_FWD_CORE wxEventLoopImpl;
|
2004-07-30 18:54:31 -04:00
|
|
|
|
2008-03-26 11:06:00 -04:00
|
|
|
class WXDLLIMPEXP_CORE wxGUIEventLoop : public wxEventLoopBase
|
2004-07-30 18:54:31 -04:00
|
|
|
{
|
|
|
|
public:
|
2007-05-14 19:43:39 -04:00
|
|
|
wxGUIEventLoop() { m_impl = NULL; }
|
|
|
|
virtual ~wxGUIEventLoop();
|
2004-09-13 14:03:44 -04:00
|
|
|
|
2004-07-30 18:54:31 -04:00
|
|
|
virtual int Run();
|
|
|
|
virtual void Exit(int rc = 0);
|
|
|
|
virtual bool Pending() const;
|
|
|
|
virtual bool Dispatch();
|
2008-12-26 19:04:57 -05:00
|
|
|
virtual int DispatchTimeout(unsigned long timeout)
|
|
|
|
{
|
|
|
|
// TODO: this is, of course, horribly inefficient and a proper wait with
|
|
|
|
// timeout should be implemented for all ports natively...
|
|
|
|
const wxMilliClock_t timeEnd = wxGetLocalTimeMillis() + timeout;
|
|
|
|
for ( ;; )
|
|
|
|
{
|
|
|
|
if ( Pending() )
|
|
|
|
return Dispatch();
|
|
|
|
|
|
|
|
if ( wxGetLocalTimeMillis() >= timeEnd )
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2007-05-14 19:43:39 -04:00
|
|
|
virtual void WakeUp() { }
|
2009-02-15 09:25:08 -05:00
|
|
|
virtual bool YieldFor(long eventsToProcess);
|
2004-07-30 18:54:31 -04:00
|
|
|
|
|
|
|
protected:
|
2003-09-17 19:32:32 -04:00
|
|
|
// the pointer to the port specific implementation class
|
|
|
|
wxEventLoopImpl *m_impl;
|
|
|
|
|
2009-02-08 06:45:59 -05:00
|
|
|
wxDECLARE_NO_COPY_CLASS(wxGUIEventLoop);
|
2006-01-12 15:09:00 -05:00
|
|
|
};
|
2004-07-30 18:54:31 -04:00
|
|
|
|
2006-01-12 15:09:00 -05:00
|
|
|
#endif // platforms
|
2001-06-29 13:21:17 -04:00
|
|
|
|
2007-05-14 19:43:39 -04:00
|
|
|
// also include the header defining wxConsoleEventLoop for Unix systems
|
|
|
|
#if defined(__UNIX__)
|
|
|
|
#include "wx/unix/evtloop.h"
|
|
|
|
#endif
|
|
|
|
|
2007-05-21 22:30:01 -04:00
|
|
|
// we use a class rather than a typedef because wxEventLoop is forward-declared
|
|
|
|
// in many places
|
2007-05-14 19:43:39 -04:00
|
|
|
#if wxUSE_GUI
|
2007-05-21 22:30:01 -04:00
|
|
|
class wxEventLoop : public wxGUIEventLoop { };
|
|
|
|
#else // !GUI
|
|
|
|
// we can't define wxEventLoop differently in GUI and base libraries so use
|
|
|
|
// a #define to still allow writing wxEventLoop in the user code
|
2008-08-25 15:23:26 -04:00
|
|
|
#if wxUSE_CONSOLE_EVENTLOOP && (defined(__WXMSW__) || defined(__UNIX__))
|
2007-05-21 22:30:01 -04:00
|
|
|
#define wxEventLoop wxConsoleEventLoop
|
|
|
|
#else // we still must define it somehow for the code below...
|
|
|
|
#define wxEventLoop wxEventLoopBase
|
|
|
|
#endif
|
2007-05-14 19:43:39 -04:00
|
|
|
#endif
|
|
|
|
|
2006-01-12 11:56:48 -05:00
|
|
|
inline bool wxEventLoopBase::IsRunning() const { return GetActive() == this; }
|
|
|
|
|
2007-05-14 19:43:39 -04:00
|
|
|
#if wxUSE_GUI
|
2003-09-17 19:32:32 -04:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// wxModalEventLoop
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// this is a naive generic implementation which uses wxWindowDisabler to
|
|
|
|
// implement modality, we will surely need platform-specific implementations
|
|
|
|
// too, this generic implementation is here only temporarily to see how it
|
|
|
|
// works
|
2008-03-26 11:06:00 -04:00
|
|
|
class WXDLLIMPEXP_CORE wxModalEventLoop : public wxGUIEventLoop
|
2003-09-17 19:32:32 -04:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
wxModalEventLoop(wxWindow *winModal)
|
|
|
|
{
|
|
|
|
m_windowDisabler = new wxWindowDisabler(winModal);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual void OnExit()
|
|
|
|
{
|
|
|
|
delete m_windowDisabler;
|
|
|
|
m_windowDisabler = NULL;
|
|
|
|
|
2007-05-14 19:43:39 -04:00
|
|
|
wxGUIEventLoop::OnExit();
|
2003-09-17 19:32:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
wxWindowDisabler *m_windowDisabler;
|
|
|
|
};
|
|
|
|
|
2007-05-14 19:43:39 -04:00
|
|
|
#endif //wxUSE_GUI
|
|
|
|
|
2006-01-12 11:56:48 -05:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// wxEventLoopActivator: helper class for wxEventLoop implementations
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// this object sets the wxEventLoop given to the ctor as the currently active
|
|
|
|
// one and unsets it in its dtor, this is especially useful in presence of
|
|
|
|
// exceptions but is more tidy even when we don't use them
|
|
|
|
class wxEventLoopActivator
|
|
|
|
{
|
|
|
|
public:
|
2007-05-14 19:43:39 -04:00
|
|
|
wxEventLoopActivator(wxEventLoopBase *evtLoop)
|
2006-01-12 11:56:48 -05:00
|
|
|
{
|
2007-05-14 19:43:39 -04:00
|
|
|
m_evtLoopOld = wxEventLoopBase::GetActive();
|
2007-05-21 22:30:01 -04:00
|
|
|
wxEventLoopBase::SetActive(evtLoop);
|
2006-01-12 11:56:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
~wxEventLoopActivator()
|
|
|
|
{
|
|
|
|
// restore the previously active event loop
|
2007-05-14 19:43:39 -04:00
|
|
|
wxEventLoopBase::SetActive(m_evtLoopOld);
|
2006-01-12 11:56:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2007-05-21 22:30:01 -04:00
|
|
|
wxEventLoopBase *m_evtLoopOld;
|
2006-01-12 11:56:48 -05:00
|
|
|
};
|
|
|
|
|
2008-08-25 15:23:26 -04:00
|
|
|
#if wxUSE_CONSOLE_EVENTLOOP
|
|
|
|
|
2008-05-16 08:50:26 -04:00
|
|
|
class wxEventLoopGuarantor
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
wxEventLoopGuarantor()
|
|
|
|
{
|
|
|
|
m_evtLoopNew = NULL;
|
|
|
|
if (!wxEventLoop::GetActive())
|
|
|
|
{
|
|
|
|
m_evtLoopNew = new wxEventLoop;
|
|
|
|
wxEventLoop::SetActive(m_evtLoopNew);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
~wxEventLoopGuarantor()
|
|
|
|
{
|
|
|
|
if (m_evtLoopNew)
|
|
|
|
{
|
|
|
|
wxEventLoop::SetActive(NULL);
|
|
|
|
delete m_evtLoopNew;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
wxEventLoop *m_evtLoopNew;
|
|
|
|
};
|
|
|
|
|
2008-08-25 15:23:26 -04:00
|
|
|
#endif // wxUSE_CONSOLE_EVENTLOOP
|
|
|
|
|
2001-06-29 13:21:17 -04:00
|
|
|
#endif // _WX_EVTLOOP_H_
|