diff --git a/include/wx/evtloop.h b/include/wx/evtloop.h index 2abbd9cef4..a9034aeac8 100644 --- a/include/wx/evtloop.h +++ b/include/wx/evtloop.h @@ -79,9 +79,9 @@ public: #if wxUSE_EVENTLOOP_SOURCE // create a new event loop source wrapping the given file descriptor and - // start monitoring it - virtual wxEventLoopSource * - AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags) = 0; + // monitor it for events occurring on this descriptor in all event loops + static wxEventLoopSource * + AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags); #endif // wxUSE_EVENTLOOP_SOURCE // dispatch&processing @@ -296,19 +296,6 @@ public: wxGUIEventLoop() { m_impl = NULL; } virtual ~wxGUIEventLoop(); -#if wxUSE_EVENTLOOP_SOURCE - // We need to define a base class pure virtual method but we can't provide - // a generic implementation for it so simply fail. - virtual wxEventLoopSource * - AddSourceForFD(int WXUNUSED(fd), - wxEventLoopSourceHandler * WXUNUSED(handler), - int WXUNUSED(flags)) - { - wxFAIL_MSG( "support for event loop sources not implemented" ); - return NULL; - } -#endif // wxUSE_EVENTLOOP_SOURCE - virtual void ScheduleExit(int rc = 0); virtual bool Pending() const; virtual bool Dispatch(); diff --git a/include/wx/gtk/evtloop.h b/include/wx/gtk/evtloop.h index af4d00348d..9fb55aa226 100644 --- a/include/wx/gtk/evtloop.h +++ b/include/wx/gtk/evtloop.h @@ -29,11 +29,6 @@ public: virtual void WakeUp(); virtual bool YieldFor(long eventsToProcess); -#if wxUSE_EVENTLOOP_SOURCE - virtual wxEventLoopSource * - AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags); -#endif // wxUSE_EVENTLOOP_SOURCE - void StoreGdkEventForLaterProcessing(GdkEvent* ev) { m_arrGdkEvents.Add(ev); } diff --git a/include/wx/osx/core/evtloop.h b/include/wx/osx/core/evtloop.h index 862a4d9d54..5bc53b0c16 100644 --- a/include/wx/osx/core/evtloop.h +++ b/include/wx/osx/core/evtloop.h @@ -45,11 +45,6 @@ public: virtual bool YieldFor(long eventsToProcess); -#if wxUSE_EVENTLOOP_SOURCE - virtual wxEventLoopSource * - AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags); -#endif // wxUSE_EVENTLOOP_SOURCE - bool ShouldProcessIdleEvents() const { return m_processIdleEvents ; } #if wxUSE_UIACTIONSIMULATOR diff --git a/include/wx/osx/evtloopsrc.h b/include/wx/osx/evtloopsrc.h index 3c18bba764..646190eb72 100644 --- a/include/wx/osx/evtloopsrc.h +++ b/include/wx/osx/evtloopsrc.h @@ -17,7 +17,7 @@ typedef struct __CFFileDescriptor *CFFileDescriptorRef; // wxCFEventLoopSource: CoreFoundation-based wxEventLoopSource for OS X // ---------------------------------------------------------------------------- -class wxCFEventLoopSource : public wxEventLoopSource +class WXDLLIMPEXP_BASE wxCFEventLoopSource : public wxEventLoopSource { public: wxCFEventLoopSource(wxEventLoopSourceHandler *handler, int flags) diff --git a/include/wx/private/eventloopsourcesmanager.h b/include/wx/private/eventloopsourcesmanager.h new file mode 100644 index 0000000000..82aadf5243 --- /dev/null +++ b/include/wx/private/eventloopsourcesmanager.h @@ -0,0 +1,26 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/private/eventloopsourcesmanager.h +// Purpose: declares wxEventLoopSourcesManagerBase class +// Author: Rob Bresalier +// Created: 2013-06-19 +// RCS-ID: $Id$ +// Copyright: (c) 2013 Rob Bresalier +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_PRIVATE_EVENTLOOPSOURCESMANAGER_H_ +#define _WX_PRIVATE_EVENTLOOPSOURCESMANAGER_H_ + +// For pulling in the value of wxUSE_EVENTLOOP_SOURCE +#include "wx/evtloop.h" + +class WXDLLIMPEXP_BASE wxEventLoopSourcesManagerBase +{ +public: +#if wxUSE_EVENTLOOP_SOURCE + virtual wxEventLoopSource* + AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags) = 0; +#endif +}; + +#endif // _WX_PRIVATE_EVENTLOOPSOURCESMANAGER_H_ diff --git a/include/wx/unix/apptbase.h b/include/wx/unix/apptbase.h index 8bf6b4cb97..fd624aeed4 100644 --- a/include/wx/unix/apptbase.h +++ b/include/wx/unix/apptbase.h @@ -15,6 +15,7 @@ struct wxEndProcessData; struct wxExecuteData; class wxFDIOManager; +class wxEventLoopSourcesManagerBase; // ---------------------------------------------------------------------------- // wxAppTraits: the Unix version adds extra hooks needed by Unix code @@ -56,6 +57,10 @@ public: virtual wxFDIOManager *GetFDIOManager(); #endif // wxUSE_SOCKETS + // Return a non-NULL pointer to the object responsible for managing the + // event loop sources in this kind of application. + virtual wxEventLoopSourcesManagerBase* GetEventLoopSourcesManager(); + protected: // a helper for the implementation of WaitForChild() in wxGUIAppTraits: // checks the streams used for redirected IO in execData and returns true diff --git a/include/wx/unix/apptrait.h b/include/wx/unix/apptrait.h index 04109204e9..5f56733d28 100644 --- a/include/wx/unix/apptrait.h +++ b/include/wx/unix/apptrait.h @@ -88,6 +88,8 @@ public: #endif #endif // wxUSE_SOCKETS + + virtual wxEventLoopSourcesManagerBase* GetEventLoopSourcesManager(); }; #endif // wxUSE_GUI diff --git a/include/wx/unix/evtloop.h b/include/wx/unix/evtloop.h index 5f1cf59ea1..0b71766068 100644 --- a/include/wx/unix/evtloop.h +++ b/include/wx/unix/evtloop.h @@ -41,11 +41,6 @@ public: virtual bool IsOk() const { return m_dispatcher != NULL; } virtual bool YieldFor(long WXUNUSED(eventsToProcess)) { return true; } -#if wxUSE_EVENTLOOP_SOURCE - virtual wxEventLoopSource * - AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags); -#endif // wxUSE_EVENTLOOP_SOURCE - protected: virtual void OnNextIteration(); diff --git a/src/common/evtloopcmn.cpp b/src/common/evtloopcmn.cpp index da0b79fba4..8564f52517 100644 --- a/src/common/evtloopcmn.cpp +++ b/src/common/evtloopcmn.cpp @@ -23,6 +23,8 @@ #endif //WX_PRECOMP #include "wx/scopeguard.h" +#include "wx/apptrait.h" +#include "wx/private/eventloopsourcesmanager.h" // ---------------------------------------------------------------------------- // wxEventLoopBase @@ -115,6 +117,29 @@ bool wxEventLoopBase::Yield(bool onlyIfNeeded) return YieldFor(wxEVT_CATEGORY_ALL); } +#if wxUSE_EVENTLOOP_SOURCE + +wxEventLoopSource* +wxEventLoopBase::AddSourceForFD(int fd, + wxEventLoopSourceHandler *handler, + int flags) +{ + // Ensure that we have some valid traits. + wxConsoleAppTraits traitsConsole; + wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL; + if ( !traits ) + traits = &traitsConsole; + + // And delegate to the event loop sources manager defined by it. + wxEventLoopSourcesManagerBase* const + manager = traits->GetEventLoopSourcesManager(); + wxCHECK_MSG( manager, NULL, wxS("Must have wxEventLoopSourcesManager") ); + + return manager->AddSourceForFD(fd, handler, flags); +} + +#endif // wxUSE_EVENTLOOP_SOURCE + // wxEventLoopManual is unused in the other ports #if defined(__WINDOWS__) || defined(__WXDFB__) || ( ( defined(__UNIX__) && !defined(__WXOSX__) ) && wxUSE_BASE) diff --git a/src/gtk/evtloop.cpp b/src/gtk/evtloop.cpp index d104d82f0c..ea5b43b9d1 100644 --- a/src/gtk/evtloop.cpp +++ b/src/gtk/evtloop.cpp @@ -32,6 +32,9 @@ #include "wx/log.h" #endif // WX_PRECOMP +#include "wx/private/eventloopsourcesmanager.h" +#include "wx/apptrait.h" + #include #include @@ -133,41 +136,50 @@ static gboolean wx_on_channel_event(GIOChannel *channel, } } -wxEventLoopSource * -wxGUIEventLoop::AddSourceForFD(int fd, - wxEventLoopSourceHandler *handler, - int flags) +class wxGUIEventLoopSourcesManager : public wxEventLoopSourcesManagerBase { - wxCHECK_MSG( fd != -1, NULL, "can't monitor invalid fd" ); +public: + virtual wxEventLoopSource* + AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags) + { + wxCHECK_MSG( fd != -1, NULL, "can't monitor invalid fd" ); - int condition = 0; - if (flags & wxEVENT_SOURCE_INPUT) - condition |= G_IO_IN | G_IO_PRI; - if (flags & wxEVENT_SOURCE_OUTPUT) - condition |= G_IO_OUT; - if (flags & wxEVENT_SOURCE_EXCEPTION) - condition |= G_IO_ERR | G_IO_HUP | G_IO_NVAL; + int condition = 0; + if ( flags & wxEVENT_SOURCE_INPUT ) + condition |= G_IO_IN | G_IO_PRI | G_IO_HUP; + if ( flags & wxEVENT_SOURCE_OUTPUT ) + condition |= G_IO_OUT; + if ( flags & wxEVENT_SOURCE_EXCEPTION ) + condition |= G_IO_ERR | G_IO_NVAL; - GIOChannel* channel = g_io_channel_unix_new(fd); - const unsigned sourceId = g_io_add_watch - ( - channel, - (GIOCondition)condition, - &wx_on_channel_event, - handler - ); - // it was ref'd by g_io_add_watch() so we can unref it here - g_io_channel_unref(channel); + GIOChannel* channel = g_io_channel_unix_new(fd); + const unsigned sourceId = g_io_add_watch + ( + channel, + (GIOCondition)condition, + &wx_on_channel_event, + handler + ); + // it was ref'd by g_io_add_watch() so we can unref it here + g_io_channel_unref(channel); - if ( !sourceId ) - return NULL; + if ( !sourceId ) + return NULL; - wxLogTrace(wxTRACE_EVT_SOURCE, - "Adding event loop source for fd=%d with GTK id=%u", - fd, sourceId); + wxLogTrace(wxTRACE_EVT_SOURCE, + "Adding event loop source for fd=%d with GTK id=%u", + fd, sourceId); - return new wxGTKEventLoopSource(sourceId, handler, flags); + return new wxGTKEventLoopSource(sourceId, handler, flags); + } +}; + +wxEventLoopSourcesManagerBase* wxGUIAppTraits::GetEventLoopSourcesManager() +{ + static wxGUIEventLoopSourcesManager s_eventLoopSourcesManager; + + return &s_eventLoopSourcesManager; } wxGTKEventLoopSource::~wxGTKEventLoopSource() diff --git a/src/osx/core/evtloop_cf.cpp b/src/osx/core/evtloop_cf.cpp index 12ecb2c872..704a833413 100644 --- a/src/osx/core/evtloop_cf.cpp +++ b/src/osx/core/evtloop_cf.cpp @@ -48,80 +48,6 @@ #if wxUSE_EVENTLOOP_SOURCE -namespace -{ - -void EnableDescriptorCallBacks(CFFileDescriptorRef cffd, int flags) -{ - if ( flags & wxEVENT_SOURCE_INPUT ) - CFFileDescriptorEnableCallBacks(cffd, kCFFileDescriptorReadCallBack); - if ( flags & wxEVENT_SOURCE_OUTPUT ) - CFFileDescriptorEnableCallBacks(cffd, kCFFileDescriptorWriteCallBack); -} - -void -wx_cffiledescriptor_callback(CFFileDescriptorRef cffd, - CFOptionFlags flags, - void *ctxData) -{ - wxLogTrace(wxTRACE_EVT_SOURCE, - "CFFileDescriptor callback, flags=%d", flags); - - wxCFEventLoopSource * const - source = static_cast(ctxData); - - wxEventLoopSourceHandler * const - handler = source->GetHandler(); - if ( flags & kCFFileDescriptorReadCallBack ) - handler->OnReadWaiting(); - if ( flags & kCFFileDescriptorWriteCallBack ) - handler->OnWriteWaiting(); - - // we need to re-enable callbacks to be called again - EnableDescriptorCallBacks(cffd, source->GetFlags()); -} - -} // anonymous namespace - -wxEventLoopSource * -wxCFEventLoop::AddSourceForFD(int fd, - wxEventLoopSourceHandler *handler, - int flags) -{ - wxCHECK_MSG( fd != -1, NULL, "can't monitor invalid fd" ); - - wxScopedPtr - source(new wxCFEventLoopSource(handler, flags)); - - CFFileDescriptorContext ctx = { 0, source.get(), NULL, NULL, NULL }; - wxCFRef - cffd(CFFileDescriptorCreate - ( - kCFAllocatorDefault, - fd, - true, // close on invalidate - wx_cffiledescriptor_callback, - &ctx - )); - if ( !cffd ) - return NULL; - - wxCFRef - cfsrc(CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, cffd, 0)); - if ( !cfsrc ) - return NULL; - - CFRunLoopRef cfloop = CFGetCurrentRunLoop(); - CFRunLoopAddSource(cfloop, cfsrc, kCFRunLoopDefaultMode); - - // Enable the callbacks initially. - EnableDescriptorCallBacks(cffd, source->GetFlags()); - - source->SetFileDescriptor(cffd.release()); - - return source.release(); -} - void wxCFEventLoopSource::SetFileDescriptor(CFFileDescriptorRef cffd) { wxASSERT_MSG( !m_cffd, "shouldn't be called more than once" ); diff --git a/src/osx/core/utilsexc_cf.cpp b/src/osx/core/utilsexc_cf.cpp index fe010f63be..221bbb322d 100644 --- a/src/osx/core/utilsexc_cf.cpp +++ b/src/osx/core/utilsexc_cf.cpp @@ -22,8 +22,13 @@ #include "wx/thread.h" #include "wx/process.h" +#include "wx/evtloop.h" +#include "wx/evtloopsrc.h" +#include "wx/private/eventloopsourcesmanager.h" + #include +#include #include /*! @@ -104,6 +109,93 @@ int wxGUIAppTraits::AddProcessCallback(wxEndProcessData *proc_data, int fd) return ++s_last_tag; } +#if wxUSE_EVENTLOOP_SOURCE + +namespace +{ + +void EnableDescriptorCallBacks(CFFileDescriptorRef cffd, int flags) +{ + if ( flags & wxEVENT_SOURCE_INPUT ) + CFFileDescriptorEnableCallBacks(cffd, kCFFileDescriptorReadCallBack); + if ( flags & wxEVENT_SOURCE_OUTPUT ) + CFFileDescriptorEnableCallBacks(cffd, kCFFileDescriptorWriteCallBack); +} + +void +wx_cffiledescriptor_callback(CFFileDescriptorRef cffd, + CFOptionFlags flags, + void *ctxData) +{ + wxLogTrace(wxTRACE_EVT_SOURCE, + "CFFileDescriptor callback, flags=%d", flags); + + wxCFEventLoopSource * const + source = static_cast(ctxData); + + wxEventLoopSourceHandler * const + handler = source->GetHandler(); + if ( flags & kCFFileDescriptorReadCallBack ) + handler->OnReadWaiting(); + if ( flags & kCFFileDescriptorWriteCallBack ) + handler->OnWriteWaiting(); + + // we need to re-enable callbacks to be called again + EnableDescriptorCallBacks(cffd, source->GetFlags()); +} + +} // anonymous namespace + +class wxCFEventLoopSourcesManager : public wxEventLoopSourcesManagerBase +{ +public: + wxEventLoopSource * + AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags) + { + wxCHECK_MSG( fd != -1, NULL, "can't monitor invalid fd" ); + + wxScopedPtr + source(new wxCFEventLoopSource(handler, flags)); + + CFFileDescriptorContext ctx = { 0, source.get(), NULL, NULL, NULL }; + wxCFRef + cffd(CFFileDescriptorCreate + ( + kCFAllocatorDefault, + fd, + true, // close on invalidate + wx_cffiledescriptor_callback, + &ctx + )); + if ( !cffd ) + return NULL; + + wxCFRef + cfsrc(CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, cffd, 0)); + if ( !cfsrc ) + return NULL; + + CFRunLoopRef cfloop = CFRunLoopGetCurrent(); + CFRunLoopAddSource(cfloop, cfsrc, kCFRunLoopDefaultMode); + + // Enable the callbacks initially. + EnableDescriptorCallBacks(cffd, source->GetFlags()); + + source->SetFileDescriptor(cffd.release()); + + return source.release(); + } +}; + +wxEventLoopSourcesManagerBase* wxGUIAppTraits::GetEventLoopSourcesManager() +{ + static wxCFEventLoopSourcesManager s_eventLoopSourcesManager; + + return &s_eventLoopSourcesManager; +} + +#endif // wxUSE_EVENTLOOP_SOURCE + ///////////////////////////////////////////////////////////////////////////// // NOTE: This doesn't really belong here but this was a handy file to diff --git a/src/unix/evtloopunix.cpp b/src/unix/evtloopunix.cpp index 784241c663..763b73ef73 100644 --- a/src/unix/evtloopunix.cpp +++ b/src/unix/evtloopunix.cpp @@ -36,7 +36,9 @@ #include "wx/unix/private/epolldispatcher.h" #include "wx/unix/private/wakeuppipe.h" #include "wx/private/selectdispatcher.h" +#include "wx/private/eventloopsourcesmanager.h" #include "wx/private/fdioeventloopsourcehandler.h" +#include "wx/private/eventloopsourcesmanager.h" #if wxUSE_EVENTLOOP_SOURCE #include "wx/evtloopsrc.h" @@ -87,27 +89,37 @@ wxConsoleEventLoop::~wxConsoleEventLoop() #if wxUSE_EVENTLOOP_SOURCE -wxEventLoopSource * -wxConsoleEventLoop::AddSourceForFD(int fd, - wxEventLoopSourceHandler *handler, - int flags) +class wxConsoleEventLoopSourcesManager : public wxEventLoopSourcesManagerBase { - wxCHECK_MSG( fd != -1, NULL, "can't monitor invalid fd" ); +public: + wxEventLoopSource* AddSourceForFD( int fd, + wxEventLoopSourceHandler *handler, + int flags) + { + wxCHECK_MSG( fd != -1, NULL, "can't monitor invalid fd" ); - wxLogTrace(wxTRACE_EVT_SOURCE, - "Adding event loop source for fd=%d", fd); + wxLogTrace(wxTRACE_EVT_SOURCE, + "Adding event loop source for fd=%d", fd); - // we need a bridge to wxFDIODispatcher - // - // TODO: refactor the code so that only wxEventLoopSourceHandler is used - wxScopedPtr - fdioHandler(new wxFDIOEventLoopSourceHandler(handler)); + // we need a bridge to wxFDIODispatcher + // + // TODO: refactor the code so that only wxEventLoopSourceHandler is used + wxScopedPtr + fdioHandler(new wxFDIOEventLoopSourceHandler(handler)); - if ( !m_dispatcher->RegisterFD(fd, fdioHandler.get(), flags) ) - return NULL; + if ( !wxFDIODispatcher::Get()->RegisterFD(fd, fdioHandler.get(), flags) ) + return NULL; - return new wxUnixEventLoopSource(m_dispatcher, fdioHandler.release(), - fd, handler, flags); + return new wxUnixEventLoopSource(wxFDIODispatcher::Get(), fdioHandler.release(), + fd, handler, flags); + } +}; + +wxEventLoopSourcesManagerBase* wxAppTraits::GetEventLoopSourcesManager() +{ + static wxConsoleEventLoopSourcesManager s_eventLoopSourcesManager; + + return &s_eventLoopSourcesManager; } wxUnixEventLoopSource::~wxUnixEventLoopSource()