added wxEventLoop::DispatchTimeout()
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57571 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -291,6 +291,7 @@ All:
|
||||
- Added wxMemoryInputStream(wxInputStream&) ctor (Stas Sergeev).
|
||||
- Implemented wxMemoryInputStream::CanRead().
|
||||
- Implemented wxMemoryFSHandler::FindFirst/Next().
|
||||
- Added wxEventLoop::DispatchTimeout().
|
||||
- Added wxEXEC_BLOCK flag (Hank Schultz).
|
||||
- Add support for wxStream-derived classes to wxRTTI (Stas Sergeev).
|
||||
- Added wxStreamBuffer::Truncate() (Stas Sergeev).
|
||||
|
@@ -27,6 +27,7 @@ public:
|
||||
|
||||
virtual bool Pending() const;
|
||||
virtual bool Dispatch();
|
||||
virtual int DispatchTimeout(unsigned long timeout);
|
||||
|
||||
// returns DirectFB event buffer used by wx
|
||||
static wxIDirectFBEventBufferPtr GetDirectFBEventBuffer();
|
||||
|
@@ -31,6 +31,7 @@ public:
|
||||
// using it
|
||||
virtual bool IsOk() const { return true; }
|
||||
|
||||
|
||||
// start the event loop, return the exit code when it is finished
|
||||
virtual int Run() = 0;
|
||||
|
||||
@@ -43,6 +44,12 @@ public:
|
||||
// dispatch a single event, return false if we should exit from the loop
|
||||
virtual bool Dispatch() = 0;
|
||||
|
||||
// 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;
|
||||
|
||||
|
||||
// return currently active (running) event loop, may be NULL
|
||||
static wxEventLoopBase *GetActive() { return ms_activeLoop; }
|
||||
|
||||
@@ -121,6 +128,8 @@ protected:
|
||||
#include "wx/dfb/evtloop.h"
|
||||
#else // other platform
|
||||
|
||||
#define wxNEEDS_GENERIC_DISPATCH_TIMEOUT
|
||||
|
||||
class WXDLLIMPEXP_FWD_CORE wxEventLoopImpl;
|
||||
|
||||
class WXDLLIMPEXP_CORE wxGUIEventLoop : public wxEventLoopBase
|
||||
@@ -133,6 +142,7 @@ public:
|
||||
virtual void Exit(int rc = 0);
|
||||
virtual bool Pending() const;
|
||||
virtual bool Dispatch();
|
||||
virtual int DispatchTimeout(unsigned long timeout);
|
||||
virtual void WakeUp() { }
|
||||
|
||||
protected:
|
||||
|
@@ -32,6 +32,10 @@ protected:
|
||||
// get the next message from queue and return true or return false if we
|
||||
// got WM_QUIT or an error occurred
|
||||
bool GetNextMessage(WXMSG *msg);
|
||||
|
||||
// same as above but with a timeout and return value can be -1 meaning that
|
||||
// time out expired in addition to
|
||||
int GetNextMessageTimeout(WXMSG *msg, unsigned long timeout);
|
||||
};
|
||||
|
||||
#if wxUSE_GUI
|
||||
@@ -66,6 +70,7 @@ public:
|
||||
|
||||
// override/implement base class virtuals
|
||||
virtual bool Dispatch();
|
||||
virtual int DispatchTimeout(unsigned long timeout);
|
||||
virtual void WakeUp();
|
||||
|
||||
protected:
|
||||
@@ -92,8 +97,12 @@ public:
|
||||
|
||||
// override/implement base class virtuals
|
||||
virtual bool Dispatch();
|
||||
virtual int DispatchTimeout(unsigned long timeout);
|
||||
virtual void WakeUp();
|
||||
|
||||
// MSW-specific function to process a single message
|
||||
virtual void ProcessMessage(WXMSG *msg);
|
||||
|
||||
protected:
|
||||
virtual void OnNextIteration();
|
||||
};
|
||||
|
@@ -12,17 +12,25 @@
|
||||
#ifndef _WX_MAC_CARBON_EVTLOOP_H_
|
||||
#define _WX_MAC_CARBON_EVTLOOP_H_
|
||||
|
||||
class OpaqueEventRef;
|
||||
typedef OpaqueEventRef *EventRef;
|
||||
|
||||
class WXDLLIMPEXP_CORE wxGUIEventLoop : public wxEventLoopManual
|
||||
{
|
||||
public:
|
||||
wxGUIEventLoop();
|
||||
|
||||
// implement/override base class pure virtual
|
||||
virtual bool Pending() const;
|
||||
virtual bool Dispatch();
|
||||
virtual int DispatchTimeout(unsigned long timeout);
|
||||
|
||||
// implement base class pure virtual
|
||||
virtual void WakeUp();
|
||||
|
||||
private:
|
||||
// dispatch an event and release it
|
||||
void DispatchAndReleaseEvent(EventRef event);
|
||||
|
||||
double m_sleepTime;
|
||||
};
|
||||
|
||||
|
@@ -26,6 +26,7 @@ public:
|
||||
virtual void Exit(int rc = 0);
|
||||
virtual bool Pending() const;
|
||||
virtual bool Dispatch();
|
||||
virtual int DispatchTimeout(unsigned long timeout);
|
||||
virtual bool IsRunning() const;
|
||||
|
||||
// MSW-specific methods
|
||||
|
@@ -29,6 +29,7 @@ public:
|
||||
// implement base class pure virtuals
|
||||
virtual bool Pending() const;
|
||||
virtual bool Dispatch();
|
||||
virtual int DispatchTimeout(unsigned long timeout);
|
||||
virtual void WakeUp();
|
||||
virtual bool IsOk() const { return m_dispatcher != NULL; }
|
||||
|
||||
|
@@ -82,6 +82,24 @@ public:
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
Return true if this event loop is currently running.
|
||||
|
||||
|
@@ -153,3 +153,23 @@ void wxEventLoopManual::Exit(int rc)
|
||||
}
|
||||
|
||||
#endif // __WXMSW__ || __WXMAC__ || __WXDFB__
|
||||
|
||||
#ifdef wxNEEDS_GENERIC_DISPATCH_TIMEOUT
|
||||
|
||||
int wxGUIEventLoop::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;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // wxNEEDS_GENERIC_DISPATCH_TIMEOUT
|
||||
|
||||
|
@@ -83,18 +83,28 @@ bool wxGUIEventLoop::Pending() const
|
||||
|
||||
bool wxGUIEventLoop::Dispatch()
|
||||
{
|
||||
wxCHECK_MSG( ms_buffer, false, "invalid event buffer" );
|
||||
|
||||
// NB: we don't block indefinitely waiting for an event, but instead
|
||||
// time out after a brief period in order to make sure that
|
||||
// OnNextIteration() will be called frequently enough
|
||||
//
|
||||
// TODO: remove this hack, instead use CreateFileDescriptor() to properly
|
||||
// multiplex GUI and socket input
|
||||
const int TIMEOUT = 100;
|
||||
|
||||
// treat time out (-1 return value) as normal successful return so that
|
||||
// OnNextIteration() is called
|
||||
return !!DispatchTimeout(TIMEOUT);
|
||||
}
|
||||
|
||||
int wxGUIEventLoop::DispatchTimeout(unsigned long timeout)
|
||||
{
|
||||
wxCHECK_MSG( ms_buffer, 0, "invalid event buffer" );
|
||||
|
||||
// release the GUI mutex so that other threads have a chance to post
|
||||
// events:
|
||||
wxMutexGuiLeave();
|
||||
|
||||
bool rv = ms_buffer->WaitForEventWithTimeout(0, TIMEOUT);
|
||||
bool rv = ms_buffer->WaitForEventWithTimeout(0, timeout);
|
||||
|
||||
// and acquire it back before calling any event handlers:
|
||||
wxMutexGuiEnter();
|
||||
@@ -112,9 +122,7 @@ bool wxGUIEventLoop::Dispatch()
|
||||
}
|
||||
|
||||
case DFB_TIMEOUT:
|
||||
// timed out, pretend we processed an event so that
|
||||
// OnNextIteration is called
|
||||
break;
|
||||
return -1;
|
||||
|
||||
default:
|
||||
// don't terminate the loop due to errors (they were reported
|
||||
@@ -123,7 +131,7 @@ bool wxGUIEventLoop::Dispatch()
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void wxGUIEventLoop::WakeUp()
|
||||
|
@@ -99,6 +99,41 @@ bool wxMSWEventLoopBase::GetNextMessage(WXMSG* msg)
|
||||
return true;
|
||||
}
|
||||
|
||||
int wxMSWEventLoopBase::GetNextMessageTimeout(WXMSG *msg, unsigned long timeout)
|
||||
{
|
||||
// MsgWaitForMultipleObjects() won't notice any input which was already
|
||||
// examined (e.g. using PeekMessage()) but not yet removed from the queue
|
||||
// so we need to remove any immediately messages manually
|
||||
//
|
||||
// NB: using MsgWaitForMultipleObjectsEx() could simplify the code here but
|
||||
// it is not available in very old Windows versions
|
||||
if ( !::PeekMessage(msg, 0, 0, 0, PM_REMOVE) )
|
||||
{
|
||||
// we use this function just in order to not block longer than the
|
||||
// given timeout, so we don't pass any handles to it at all
|
||||
if ( ::MsgWaitForMultipleObjects
|
||||
(
|
||||
0, NULL,
|
||||
FALSE,
|
||||
timeout,
|
||||
QS_ALLINPUT
|
||||
) == WAIT_TIMEOUT )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( !::PeekMessage(msg, 0, 0, 0, PM_REMOVE) )
|
||||
{
|
||||
wxFAIL_MSG( _T("PeekMessage() should have succeeded") );
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return msg->message != WM_QUIT;
|
||||
}
|
||||
|
||||
|
||||
#endif // wxUSE_BASE
|
||||
|
||||
#if wxUSE_GUI
|
||||
@@ -289,6 +324,18 @@ bool wxGUIEventLoop::Dispatch()
|
||||
return true;
|
||||
}
|
||||
|
||||
int wxGUIEventLoop::DispatchTimeout(unsigned long timeout)
|
||||
{
|
||||
MSG msg;
|
||||
int rc = GetNextMessageTimeout(&msg, timeout);
|
||||
if ( rc != 1 )
|
||||
return rc;
|
||||
|
||||
ProcessMessage(&msg);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void wxGUIEventLoop::OnNextIteration()
|
||||
{
|
||||
#if wxUSE_THREADS
|
||||
@@ -318,22 +365,39 @@ void wxConsoleEventLoop::WakeUp()
|
||||
#endif
|
||||
}
|
||||
|
||||
void wxConsoleEventLoop::ProcessMessage(WXMSG *msg)
|
||||
{
|
||||
if ( msg->message == WM_TIMER )
|
||||
{
|
||||
TIMERPROC proc = (TIMERPROC)msg->lParam;
|
||||
if ( proc )
|
||||
(*proc)(NULL, 0, msg->wParam, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
::DispatchMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
bool wxConsoleEventLoop::Dispatch()
|
||||
{
|
||||
MSG msg;
|
||||
if ( !GetNextMessage(&msg) )
|
||||
return false;
|
||||
|
||||
if ( msg.message == WM_TIMER )
|
||||
{
|
||||
TIMERPROC proc = (TIMERPROC)msg.lParam;
|
||||
if ( proc )
|
||||
(*proc)(NULL, 0, msg.wParam, 0);
|
||||
ProcessMessage(&msg);
|
||||
|
||||
return !m_shouldExit;
|
||||
}
|
||||
else
|
||||
|
||||
int wxConsoleEventLoop::DispatchTimeout(unsigned long timeout)
|
||||
{
|
||||
::DispatchMessage(&msg);
|
||||
}
|
||||
MSG msg;
|
||||
int rc = GetNextMessageTimeout(&msg, timeout);
|
||||
if ( rc != 1 )
|
||||
return rc;
|
||||
|
||||
ProcessMessage(&msg);
|
||||
|
||||
return !m_shouldExit;
|
||||
}
|
||||
|
@@ -48,6 +48,18 @@ void wxGUIEventLoop::WakeUp()
|
||||
wxMacWakeUp();
|
||||
}
|
||||
|
||||
void wxGUIEventLoop::DispatchAndReleaseEvent(EventRef theEvent)
|
||||
{
|
||||
if ( wxTheApp )
|
||||
wxTheApp->MacSetCurrentEvent( theEvent, NULL );
|
||||
|
||||
OSStatus status = SendEventToEventTarget(theEvent, GetEventDispatcherTarget());
|
||||
if (status == eventNotHandledErr && wxTheApp)
|
||||
wxTheApp->MacHandleUnhandledEvent(theEvent);
|
||||
|
||||
ReleaseEvent( theEvent );
|
||||
}
|
||||
|
||||
bool wxGUIEventLoop::Pending() const
|
||||
{
|
||||
EventRef theEvent;
|
||||
@@ -95,17 +107,33 @@ bool wxGUIEventLoop::Dispatch()
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( wxTheApp )
|
||||
wxTheApp->MacSetCurrentEvent( theEvent, NULL );
|
||||
|
||||
OSStatus status = SendEventToEventTarget(theEvent, GetEventDispatcherTarget());
|
||||
if (status == eventNotHandledErr && wxTheApp)
|
||||
wxTheApp->MacHandleUnhandledEvent(theEvent);
|
||||
|
||||
ReleaseEvent( theEvent );
|
||||
DispatchAndReleaseEvent(theEvent);
|
||||
m_sleepTime = kEventDurationNoWait ;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int wxGUIEventLoop::DispatchTimeout(unsigned long timeout)
|
||||
{
|
||||
EventRef event;
|
||||
OSStatus status = ReceiveNextEvent(0, NULL, timeout/1000, true, &event);
|
||||
switch ( status )
|
||||
{
|
||||
default:
|
||||
wxFAIL_MSG( "unexpected ReceiveNextEvent() error" );
|
||||
// fall through
|
||||
|
||||
case eventLoopTimedOutErr:
|
||||
return -1;
|
||||
|
||||
case eventLoopQuitErr:
|
||||
return 0;
|
||||
|
||||
case noErr:
|
||||
DispatchAndReleaseEvent(event);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -135,6 +135,11 @@ bool wxGUIEventLoop::Dispatch()
|
||||
return false;
|
||||
}
|
||||
|
||||
int wxGUIEventLoop::DispatchTimeout(unsigned long timeout)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void wxGUIEventLoop::WakeUp()
|
||||
{
|
||||
return;
|
||||
|
@@ -149,30 +149,34 @@ bool wxConsoleEventLoop::Pending() const
|
||||
|
||||
bool wxConsoleEventLoop::Dispatch()
|
||||
{
|
||||
// calculate the timeout until the next timer expiration
|
||||
int timeout;
|
||||
DispatchTimeout(wxFDIODispatcher::TIMEOUT_INFINITE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int wxConsoleEventLoop::DispatchTimeout(unsigned long timeout)
|
||||
{
|
||||
#if wxUSE_TIMER
|
||||
// check if we need to decrease the timeout to account for a timer
|
||||
wxUsecClock_t nextTimer;
|
||||
if ( wxTimerScheduler::Get().GetNext(&nextTimer) )
|
||||
{
|
||||
// timeout is in ms
|
||||
timeout = (nextTimer / 1000).ToLong();
|
||||
unsigned long timeUntilNextTimer = wxMilliClockToLong(nextTimer / 1000);
|
||||
if ( timeUntilNextTimer < timeout )
|
||||
timeout = timeUntilNextTimer;
|
||||
}
|
||||
else // no timers, we can block forever
|
||||
#endif // wxUSE_TIMER
|
||||
{
|
||||
timeout = wxFDIODispatcher::TIMEOUT_INFINITE;
|
||||
}
|
||||
|
||||
m_dispatcher->Dispatch(timeout);
|
||||
bool hadEvent = m_dispatcher->Dispatch(timeout);
|
||||
|
||||
#if wxUSE_TIMER
|
||||
wxTimerScheduler::Get().NotifyExpired();
|
||||
#endif
|
||||
if ( wxTimerScheduler::Get().NotifyExpired() )
|
||||
hadEvent = true;
|
||||
#endif // wxUSE_TIMER
|
||||
|
||||
wxTheApp->ProcessPendingEvents();
|
||||
return true;
|
||||
|
||||
return hadEvent ? 1 : -1;
|
||||
}
|
||||
|
||||
void wxConsoleEventLoop::WakeUp()
|
||||
|
Reference in New Issue
Block a user