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:
parent
0056673c67
commit
293a13bad7
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user