#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
{
// 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;
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
//
// returns the return value of DoDispatchTimeout()
int DoProcessEvents();
+
};
#if wxUSE_GUI
#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()
CFRunLoopRef wxCFEventLoop::CFGetCurrentRunLoop() const
{
- return CFGetCurrentRunLoop();
+ return CFRunLoopGetCurrent();
}
void wxCFEventLoop::WakeUp()
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)
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;
}
{
m_exitcode = rc;
m_shouldExit = true;
- m_sleepTime = 0;
}