streamlining OSX event support second step, moving pending and idle event handling to runloop-observer, see #11805, see #11797

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@63689 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Stefan Csomor 2010-03-15 19:31:57 +00:00
parent 0056673c67
commit 293a13bad7
2 changed files with 58 additions and 31 deletions

View File

@ -13,7 +13,8 @@
#ifndef _WX_OSX_EVTLOOP_H_
#define _WX_OSX_EVTLOOP_H_
typedef struct __CFRunLoop * CFRunLoopRef;
DECLARE_WXOSX_OPAQUE_CFREF( CFRunLoop );
DECLARE_WXOSX_OPAQUE_CFREF( CFRunLoopObserver );
class WXDLLIMPEXP_BASE wxCFEventLoop : public wxEventLoopBase
{
@ -28,7 +29,7 @@ public:
// sets the "should exit" flag and wakes up the loop so that it terminates
// soon
virtual void Exit(int rc = 0);
// return true if any events are available
virtual bool Pending() const;
@ -51,19 +52,22 @@ public:
AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags);
#endif // wxUSE_EVENTLOOP_SOURCE
void ObserverCallBack(CFRunLoopObserverRef observer, int activity);
protected:
// get the currently executing CFRunLoop
virtual CFRunLoopRef CFGetCurrentRunLoop() const;
virtual int DoDispatchTimeout(unsigned long timeout);
double m_sleepTime;
// should we exit the loop?
bool m_shouldExit;
// the loop exit code
int m_exitcode;
// runloop observer
CFRunLoopObserverRef m_runLoopObserver;
private:
// process all already pending events and dispatch a new one (blocking
@ -71,6 +75,7 @@ private:
//
// returns the return value of DoDispatchTimeout()
int DoProcessEvents();
};
#if wxUSE_GUI

View File

@ -142,10 +142,55 @@ wxCFEventLoop::AddSourceForFD(int WXUNUSED(fd),
#endif // wxUSE_EVENTLOOP_SOURCE
void wxObserverCallBack(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info)
{
wxCFEventLoop * eventloop = static_cast<wxCFEventLoop *>(info);
if ( eventloop )
eventloop->ObserverCallBack(observer, activity);
}
void wxCFEventLoop::ObserverCallBack(CFRunLoopObserverRef observer, int activity)
{
if ( activity & kCFRunLoopBeforeTimers )
{
// process pending wx events first as they correspond to low-level events
// which happened before, i.e. typically pending events were queued by a
// previous call to Dispatch() and if we didn't process them now the next
// call to it might enqueue them again (as happens with e.g. socket events
// which would be generated as long as there is input available on socket
// and this input is only removed from it when pending event handlers are
// executed)
if ( wxTheApp )
wxTheApp->ProcessPendingEvents();
}
if ( activity & kCFRunLoopBeforeWaiting )
{
if ( ProcessIdle() )
{
WakeUp();
}
else
{
#if wxUSE_THREADS
wxMutexGuiLeave();
wxMilliSleep(20);
wxMutexGuiEnter();
#endif
}
}
}
wxCFEventLoop::wxCFEventLoop()
{
m_shouldExit = false;
m_sleepTime = 0.0;
CFRunLoopObserverContext ctxt;
bzero( &ctxt, sizeof(ctxt) );
ctxt.info = this;
m_runLoopObserver = CFRunLoopObserverCreate( kCFAllocatorDefault, kCFRunLoopBeforeTimers | kCFRunLoopBeforeWaiting , true /* repeats */, 0,
wxObserverCallBack, &ctxt );
CFRunLoopAddObserver(CFGetCurrentRunLoop(), m_runLoopObserver, kCFRunLoopDefaultMode);
}
wxCFEventLoop::~wxCFEventLoop()
@ -155,7 +200,7 @@ wxCFEventLoop::~wxCFEventLoop()
CFRunLoopRef wxCFEventLoop::CFGetCurrentRunLoop() const
{
return CFGetCurrentRunLoop();
return CFRunLoopGetCurrent();
}
void wxCFEventLoop::WakeUp()
@ -214,22 +259,12 @@ bool wxCFEventLoop::Pending() const
int wxCFEventLoop::DoProcessEvents()
{
// process pending wx events first as they correspond to low-level events
// which happened before, i.e. typically pending events were queued by a
// previous call to Dispatch() and if we didn't process them now the next
// call to it might enqueue them again (as happens with e.g. socket events
// which would be generated as long as there is input available on socket
// and this input is only removed from it when pending event handlers are
// executed)
if ( wxTheApp )
wxTheApp->ProcessPendingEvents();
return DispatchTimeout( (unsigned long)(m_sleepTime * 1000.0) );
return DispatchTimeout( 1000 );
}
bool wxCFEventLoop::Dispatch()
{
return DispatchTimeout( (unsigned long)(m_sleepTime * 1000.0) ) != 0;
return DoProcessEvents() != 0;
}
int wxCFEventLoop::DispatchTimeout(unsigned long timeout)
@ -249,20 +284,8 @@ int wxCFEventLoop::DispatchTimeout(unsigned long timeout)
if ( m_shouldExit )
return 0;
if ( ProcessIdle() )
m_sleepTime = 0.0 ;
else
{
m_sleepTime = 1.0;
#if wxUSE_THREADS
wxMutexGuiLeave();
wxMilliSleep(20);
wxMutexGuiEnter();
#endif
}
break;
case 1:
m_sleepTime = 0;
break;
}
@ -367,7 +390,6 @@ void wxCFEventLoop::Exit(int rc)
{
m_exitcode = rc;
m_shouldExit = true;
m_sleepTime = 0;
}