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_
|
#ifndef _WX_OSX_EVTLOOP_H_
|
||||||
#define _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
|
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
|
// sets the "should exit" flag and wakes up the loop so that it terminates
|
||||||
// soon
|
// soon
|
||||||
virtual void Exit(int rc = 0);
|
virtual void Exit(int rc = 0);
|
||||||
|
|
||||||
// return true if any events are available
|
// return true if any events are available
|
||||||
virtual bool Pending() const;
|
virtual bool Pending() const;
|
||||||
|
|
||||||
@ -51,19 +52,22 @@ public:
|
|||||||
AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags);
|
AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags);
|
||||||
#endif // wxUSE_EVENTLOOP_SOURCE
|
#endif // wxUSE_EVENTLOOP_SOURCE
|
||||||
|
|
||||||
|
void ObserverCallBack(CFRunLoopObserverRef observer, int activity);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// get the currently executing CFRunLoop
|
// get the currently executing CFRunLoop
|
||||||
virtual CFRunLoopRef CFGetCurrentRunLoop() const;
|
virtual CFRunLoopRef CFGetCurrentRunLoop() const;
|
||||||
|
|
||||||
virtual int DoDispatchTimeout(unsigned long timeout);
|
virtual int DoDispatchTimeout(unsigned long timeout);
|
||||||
|
|
||||||
double m_sleepTime;
|
|
||||||
|
|
||||||
// should we exit the loop?
|
// should we exit the loop?
|
||||||
bool m_shouldExit;
|
bool m_shouldExit;
|
||||||
|
|
||||||
// the loop exit code
|
// the loop exit code
|
||||||
int m_exitcode;
|
int m_exitcode;
|
||||||
|
|
||||||
|
// runloop observer
|
||||||
|
CFRunLoopObserverRef m_runLoopObserver;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// process all already pending events and dispatch a new one (blocking
|
// process all already pending events and dispatch a new one (blocking
|
||||||
@ -71,6 +75,7 @@ private:
|
|||||||
//
|
//
|
||||||
// returns the return value of DoDispatchTimeout()
|
// returns the return value of DoDispatchTimeout()
|
||||||
int DoProcessEvents();
|
int DoProcessEvents();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#if wxUSE_GUI
|
#if wxUSE_GUI
|
||||||
|
@ -142,10 +142,55 @@ wxCFEventLoop::AddSourceForFD(int WXUNUSED(fd),
|
|||||||
|
|
||||||
#endif // wxUSE_EVENTLOOP_SOURCE
|
#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()
|
wxCFEventLoop::wxCFEventLoop()
|
||||||
{
|
{
|
||||||
m_shouldExit = false;
|
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()
|
wxCFEventLoop::~wxCFEventLoop()
|
||||||
@ -155,7 +200,7 @@ wxCFEventLoop::~wxCFEventLoop()
|
|||||||
|
|
||||||
CFRunLoopRef wxCFEventLoop::CFGetCurrentRunLoop() const
|
CFRunLoopRef wxCFEventLoop::CFGetCurrentRunLoop() const
|
||||||
{
|
{
|
||||||
return CFGetCurrentRunLoop();
|
return CFRunLoopGetCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxCFEventLoop::WakeUp()
|
void wxCFEventLoop::WakeUp()
|
||||||
@ -214,22 +259,12 @@ bool wxCFEventLoop::Pending() const
|
|||||||
|
|
||||||
int wxCFEventLoop::DoProcessEvents()
|
int wxCFEventLoop::DoProcessEvents()
|
||||||
{
|
{
|
||||||
// process pending wx events first as they correspond to low-level events
|
return DispatchTimeout( 1000 );
|
||||||
// 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) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxCFEventLoop::Dispatch()
|
bool wxCFEventLoop::Dispatch()
|
||||||
{
|
{
|
||||||
return DispatchTimeout( (unsigned long)(m_sleepTime * 1000.0) ) != 0;
|
return DoProcessEvents() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int wxCFEventLoop::DispatchTimeout(unsigned long timeout)
|
int wxCFEventLoop::DispatchTimeout(unsigned long timeout)
|
||||||
@ -249,20 +284,8 @@ int wxCFEventLoop::DispatchTimeout(unsigned long timeout)
|
|||||||
if ( m_shouldExit )
|
if ( m_shouldExit )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if ( ProcessIdle() )
|
|
||||||
m_sleepTime = 0.0 ;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_sleepTime = 1.0;
|
|
||||||
#if wxUSE_THREADS
|
|
||||||
wxMutexGuiLeave();
|
|
||||||
wxMilliSleep(20);
|
|
||||||
wxMutexGuiEnter();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
m_sleepTime = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,7 +390,6 @@ void wxCFEventLoop::Exit(int rc)
|
|||||||
{
|
{
|
||||||
m_exitcode = rc;
|
m_exitcode = rc;
|
||||||
m_shouldExit = true;
|
m_shouldExit = true;
|
||||||
m_sleepTime = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user