diff --git a/Makefile.in b/Makefile.in index 2b6de3e20a..48d0fa717e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -2046,6 +2046,7 @@ COND_TOOLKIT__BASE_OSX_SRC = \ src/unix/fswatcher_kqueue.cpp \ src/unix/mimetype.cpp \ src/osx/core/cfstring.cpp \ + src/osx/core/evtloop_cf.cpp \ src/osx/core/stdpaths_cf.cpp \ src/osx/core/strconv_cf.cpp \ src/osx/core/utilsexc_base.cpp @@ -2068,6 +2069,7 @@ COND_TOOLKIT_COCOA_BASE_OSX_SRC = \ src/unix/fswatcher_kqueue.cpp \ src/unix/mimetype.cpp \ src/osx/core/cfstring.cpp \ + src/osx/core/evtloop_cf.cpp \ src/osx/core/stdpaths_cf.cpp \ src/osx/core/strconv_cf.cpp \ src/osx/core/utilsexc_base.cpp @@ -2090,6 +2092,7 @@ COND_TOOLKIT_GTK_BASE_OSX_SRC = \ src/unix/fswatcher_kqueue.cpp \ src/unix/mimetype.cpp \ src/osx/core/cfstring.cpp \ + src/osx/core/evtloop_cf.cpp \ src/osx/core/stdpaths_cf.cpp \ src/osx/core/strconv_cf.cpp \ src/osx/core/utilsexc_base.cpp @@ -2112,6 +2115,7 @@ COND_TOOLKIT_MOTIF_BASE_OSX_SRC = \ src/unix/fswatcher_kqueue.cpp \ src/unix/mimetype.cpp \ src/osx/core/cfstring.cpp \ + src/osx/core/evtloop_cf.cpp \ src/osx/core/stdpaths_cf.cpp \ src/osx/core/strconv_cf.cpp \ src/osx/core/utilsexc_base.cpp @@ -2119,6 +2123,7 @@ COND_TOOLKIT_MOTIF_BASE_OSX_SRC = \ COND_TOOLKIT_OSX_CARBON_BASE_OSX_SRC = \ src/osx/core/mimetype.cpp \ src/osx/core/cfstring.cpp \ + src/osx/core/evtloop_cf.cpp \ src/osx/core/stdpaths_cf.cpp \ src/osx/core/strconv_cf.cpp \ src/osx/core/utilsexc_base.cpp \ @@ -2141,6 +2146,7 @@ COND_TOOLKIT_OSX_CARBON_BASE_OSX_SRC = \ COND_TOOLKIT_OSX_COCOA_BASE_OSX_SRC = \ src/osx/core/mimetype.cpp \ src/osx/core/cfstring.cpp \ + src/osx/core/evtloop_cf.cpp \ src/osx/core/stdpaths_cf.cpp \ src/osx/core/strconv_cf.cpp \ src/osx/core/utilsexc_base.cpp \ @@ -2178,6 +2184,7 @@ COND_TOOLKIT_X11_BASE_OSX_SRC = \ src/unix/fswatcher_kqueue.cpp \ src/unix/mimetype.cpp \ src/osx/core/cfstring.cpp \ + src/osx/core/evtloop_cf.cpp \ src/osx/core/stdpaths_cf.cpp \ src/osx/core/strconv_cf.cpp \ src/osx/core/utilsexc_base.cpp @@ -3960,6 +3967,7 @@ COND_USE_SOVERSOLARIS_1___monodll___so_symlinks_uninst_cmd = rm -f \ COND_PLATFORM_MACOSX_1___BASE_PLATFORM_SRC_OBJECTS = \ monodll_core_mimetype.o \ monodll_cfstring.o \ + monodll_evtloop_cf.o \ monodll_stdpaths_cf.o \ monodll_strconv_cf.o \ monodll_utilsexc_base.o \ @@ -5777,6 +5785,7 @@ COND_MONOLITHIC_1_SHARED_0___monolib___depname = \ COND_PLATFORM_MACOSX_1___BASE_PLATFORM_SRC_OBJECTS_1 = \ monolib_core_mimetype.o \ monolib_cfstring.o \ + monolib_evtloop_cf.o \ monolib_stdpaths_cf.o \ monolib_strconv_cf.o \ monolib_utilsexc_base.o \ @@ -7647,6 +7656,7 @@ COND_USE_SOVERSOLARIS_1___basedll___so_symlinks_uninst_cmd = rm -f \ COND_PLATFORM_MACOSX_1___BASE_PLATFORM_SRC_OBJECTS_2 = \ basedll_core_mimetype.o \ basedll_cfstring.o \ + basedll_evtloop_cf.o \ basedll_stdpaths_cf.o \ basedll_strconv_cf.o \ basedll_utilsexc_base.o \ @@ -7746,6 +7756,7 @@ COND_MONOLITHIC_0_SHARED_0___baselib___depname = \ COND_PLATFORM_MACOSX_1___BASE_PLATFORM_SRC_OBJECTS_3 = \ baselib_core_mimetype.o \ baselib_cfstring.o \ + baselib_evtloop_cf.o \ baselib_stdpaths_cf.o \ baselib_strconv_cf.o \ baselib_utilsexc_base.o \ @@ -14866,6 +14877,9 @@ monodll_core_mimetype.o: $(srcdir)/src/osx/core/mimetype.cpp $(MONODLL_ODEP) monodll_cfstring.o: $(srcdir)/src/osx/core/cfstring.cpp $(MONODLL_ODEP) $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/osx/core/cfstring.cpp +monodll_evtloop_cf.o: $(srcdir)/src/osx/core/evtloop_cf.cpp $(MONODLL_ODEP) + $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/osx/core/evtloop_cf.cpp + monodll_stdpaths_cf.o: $(srcdir)/src/osx/core/stdpaths_cf.cpp $(MONODLL_ODEP) $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/osx/core/stdpaths_cf.cpp @@ -19660,6 +19674,9 @@ monolib_core_mimetype.o: $(srcdir)/src/osx/core/mimetype.cpp $(MONOLIB_ODEP) monolib_cfstring.o: $(srcdir)/src/osx/core/cfstring.cpp $(MONOLIB_ODEP) $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/osx/core/cfstring.cpp +monolib_evtloop_cf.o: $(srcdir)/src/osx/core/evtloop_cf.cpp $(MONOLIB_ODEP) + $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/osx/core/evtloop_cf.cpp + monolib_stdpaths_cf.o: $(srcdir)/src/osx/core/stdpaths_cf.cpp $(MONOLIB_ODEP) $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/osx/core/stdpaths_cf.cpp @@ -24454,6 +24471,9 @@ basedll_core_mimetype.o: $(srcdir)/src/osx/core/mimetype.cpp $(BASEDLL_ODEP) basedll_cfstring.o: $(srcdir)/src/osx/core/cfstring.cpp $(BASEDLL_ODEP) $(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/osx/core/cfstring.cpp +basedll_evtloop_cf.o: $(srcdir)/src/osx/core/evtloop_cf.cpp $(BASEDLL_ODEP) + $(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/osx/core/evtloop_cf.cpp + basedll_stdpaths_cf.o: $(srcdir)/src/osx/core/stdpaths_cf.cpp $(BASEDLL_ODEP) $(CXXC) -c -o $@ $(BASEDLL_CXXFLAGS) $(srcdir)/src/osx/core/stdpaths_cf.cpp @@ -24946,6 +24966,9 @@ baselib_core_mimetype.o: $(srcdir)/src/osx/core/mimetype.cpp $(BASELIB_ODEP) baselib_cfstring.o: $(srcdir)/src/osx/core/cfstring.cpp $(BASELIB_ODEP) $(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/osx/core/cfstring.cpp +baselib_evtloop_cf.o: $(srcdir)/src/osx/core/evtloop_cf.cpp $(BASELIB_ODEP) + $(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/osx/core/evtloop_cf.cpp + baselib_stdpaths_cf.o: $(srcdir)/src/osx/core/stdpaths_cf.cpp $(BASELIB_ODEP) $(CXXC) -c -o $@ $(BASELIB_CXXFLAGS) $(srcdir)/src/osx/core/stdpaths_cf.cpp diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl index edcf05e6a8..7b9e19a7ae 100644 --- a/build/bakefiles/files.bkl +++ b/build/bakefiles/files.bkl @@ -79,6 +79,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! wx/unix/apptrait.h wx/unix/chkconf.h wx/unix/evtloop.h + wx/unix/evtloopsrc.h wx/unix/pipe.h wx/unix/stdpaths.h wx/unix/stackwalk.h @@ -186,6 +187,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/osx/core/cfstring.cpp + src/osx/core/evtloop_cf.cpp src/osx/core/stdpaths_cf.cpp src/osx/core/strconv_cf.cpp src/osx/core/utilsexc_base.cpp @@ -892,6 +894,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! wx/docview.h wx/effects.h wx/evtloop.h + wx/evtloopsrc.h wx/fdrepdlg.h wx/filectrl.h wx/filepicker.h @@ -1057,6 +1060,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! wx/gtk/dcscreen.h wx/gtk/dnd.h wx/gtk/evtloop.h + wx/gtk/evtloopsrc.h wx/gtk/font.h wx/gtk/minifram.h wx/gtk/pen.h @@ -2367,6 +2371,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! wx/osx/dirdlg.h wx/osx/dnd.h wx/osx/evtloop.h + wx/osx/evtloopsrc.h wx/osx/filedlg.h wx/osx/font.h wx/osx/fontdlg.h diff --git a/include/wx/evtloop.h b/include/wx/evtloop.h index 31db6dc9db..7a9495afbf 100644 --- a/include/wx/evtloop.h +++ b/include/wx/evtloop.h @@ -14,208 +14,20 @@ #include "wx/event.h" #include "wx/utils.h" -#include "wx/hashset.h" -// ---------------------------------------------------------------------------- -// wxEventLoopSource: source of i/o for wxEventLoop -// ---------------------------------------------------------------------------- - -#define wxTRACE_EVT_SOURCE "EventSource" - -#if defined(__UNIX__) && (wxUSE_CONSOLE_EVENTLOOP || defined(__WXGTK__) || \ - defined(__WXOSX_COCOA__)) +// TODO: implement wxEventLoopSource for MSW (it should wrap a HANDLE and be +// monitored using MsgWaitForMultipleObjects()) +#if defined(__WXOSX__) || defined(__WXGTK20__) || defined(__WXDFB__) || \ + (!wxUSE_GUI && defined(__UNIX__)) #define wxUSE_EVENTLOOP_SOURCE 1 #else #define wxUSE_EVENTLOOP_SOURCE 0 #endif #if wxUSE_EVENTLOOP_SOURCE - -// handler used to process events on event loop sources -class WXDLLIMPEXP_BASE wxEventLoopSourceHandler -{ -public: - // called when descriptor is available for non-blocking read - virtual void OnReadWaiting() = 0; - - // called when descriptor is available for non-blocking write - virtual void OnWriteWaiting() = 0; - - // called when there is exception on descriptor - virtual void OnExceptionWaiting() = 0; - - // virtual dtor for the base class - virtual ~wxEventLoopSourceHandler() { } -}; - -// those flags describes what events should be reported -enum -{ - wxEVENT_SOURCE_INPUT = 0x01, - wxEVENT_SOURCE_OUTPUT = 0x02, - wxEVENT_SOURCE_EXCEPTION = 0x04, - wxEVENT_SOURCE_ALL = wxEVENT_SOURCE_INPUT | wxEVENT_SOURCE_OUTPUT | - wxEVENT_SOURCE_EXCEPTION, -}; - -class wxAbstractEventLoopSource -{ -public: - wxAbstractEventLoopSource() : - m_handler(NULL), m_flags(-1) - {} - - wxAbstractEventLoopSource(wxEventLoopSourceHandler* handler, int flags) : - m_handler(handler), m_flags(flags) - {} - - virtual ~wxAbstractEventLoopSource() { } - - virtual bool IsOk() const = 0; - - virtual void Invalidate() = 0; - - void SetHandler(wxEventLoopSourceHandler* handler) - { - m_handler = handler; - } - - wxEventLoopSourceHandler* GetHandler() const - { - return m_handler; - } - - void SetFlags(int flags) - { - m_flags = flags; - } - - int GetFlags() const - { - return m_flags; - } - -protected: - wxEventLoopSourceHandler* m_handler; - int m_flags; -}; - -// This class is a simple wrapper for OS specific resources than can be a -// source of I/O. On Unix,for instance these are file descriptors. -// -// Instances of this class doesn't take resposibility of any resource you pass -// to them, I.E. you have to release them yourself. -template -class WXDLLIMPEXP_BASE wxEventLoopSourceBase : public wxAbstractEventLoopSource -{ -public: - typedef T Resource; - - // copy ctor - wxEventLoopSourceBase(const wxEventLoopSourceBase& source) : - wxAbstractEventLoopSource(source.GetHandler(), source.GetFlags()), - m_res(source.GetResource()) - { - } - - virtual const T InvalidResource() const - { - return (T)-1; - } - - virtual void Invalidate() - { - SetResource(InvalidResource()); - SetHandler(NULL); - } - - // sets internal value to res - void SetResource(T res) - { - m_res = res; - } - - // returns associated resource - T GetResource() const - { - return m_res; - } - - virtual bool IsOk() const - { - // flags < 0 are invalid and flags == 0 mean monitoring for nothing - return m_res != InvalidResource() && m_handler && m_flags >=1; - } - -protected: - // empty ctor, beacuse we often store event sources as values - wxEventLoopSourceBase() : - wxAbstractEventLoopSource(), - m_res(InvalidResource()) - { - } - - // ctor setting internal value to the os resource res - wxEventLoopSourceBase(T res, wxEventLoopSourceHandler* handler, - int flags) : - wxAbstractEventLoopSource(handler, flags), - m_res(res) - { } - - T m_res; -}; - -#if defined(__WXMAC__) -class wxMacEventLoopSource : public wxEventLoopSourceBase -{ -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - int GetFileDescriptor() const - { - return m_fd; - } + class wxEventLoopSource; + class wxEventLoopSourceHandler; #endif -protected: - wxMacEventLoopSource() : wxEventLoopSourceBase() { } - - // ctor setting internal value to the os resource res - wxMacEventLoopSource(CFRunLoopSourceRef res, - wxEventLoopSourceHandler* handler, int flags) : - wxEventLoopSourceBase(res, handler, flags) - { - } - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 - int m_fd; -#endif - - friend class wxGUIEventLoop; -}; -#endif - -#if defined(__UNIX__) -class wxUnixEventLoopSource : public wxEventLoopSourceBase -{ -protected: - wxUnixEventLoopSource() : wxEventLoopSourceBase() { } - - // ctor setting internal value to the os resource res - wxUnixEventLoopSource(int res, wxEventLoopSourceHandler* handler, - int flags) : - wxEventLoopSourceBase(res, handler, flags) - { - } - - friend class wxConsoleEventLoop; - friend class wxGUIEventLoop; -}; -#endif - -// the list of watched sources -WX_DECLARE_HASH_SET(wxAbstractEventLoopSource*, wxPointerHash, wxPointerEqual, - wxEventLoopSourceHashSet); - -#endif - /* NOTE ABOUT wxEventLoopBase::YieldFor LOGIC @@ -267,67 +79,11 @@ public: bool IsMain() const; #if wxUSE_EVENTLOOP_SOURCE - virtual wxAbstractEventLoopSource* CreateSource() const = 0; - - virtual wxAbstractEventLoopSource* CreateSource(int WXUNUSED(res), - wxEventLoopSourceHandler* WXUNUSED(handler), - int WXUNUSED(flags)) const - { - return NULL; - } - - // adds source to be monitored for I/O events specified in flags. Upon an - // event the appropriate method of handler will be called. The handler is - // owned be the calling client and will not be freed in any case. - // Returns true if the source was successfully added, false if it failed - // (this may happen for example when this source is already monitored) - virtual bool AddSource(wxAbstractEventLoopSource* source) - { - wxCHECK_MSG( source && source->IsOk(), false, "Invalid source" ); - - wxEventLoopSourceHashSet::value_type val(source); - if (!m_sourceMap.insert(val).second) - { - return false; - } - - bool ret = DoAddSource(source); - if (!ret) - { - (void) m_sourceMap.erase(source); - } - return ret; - } - - // removes the source from the list of monitored sources. - // Returns true if the source was successfully removed, false otherwise - virtual bool RemoveSource(wxAbstractEventLoopSource* source) - { - wxCHECK_MSG( source && source->IsOk(), false, "Invalid source" ); - - if (m_sourceMap.find(source) == m_sourceMap.end()) - { - return false; - } - - bool ret = DoRemoveSource(source); - m_sourceMap.erase(source); - return ret; - } - - bool RemoveAllSources() - { - wxEventLoopSourceHashSet::iterator it = m_sourceMap.begin(); - while ( !m_sourceMap.empty() ) - { - (void) RemoveSource(*it); - m_sourceMap.erase(it); - it = m_sourceMap.begin(); - } - - return true; - } -#endif + // 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; +#endif // wxUSE_EVENTLOOP_SOURCE // dispatch&processing // ------------------- @@ -414,13 +170,6 @@ public: protected: -#if wxUSE_EVENTLOOP_SOURCE - virtual bool DoAddSource(wxAbstractEventLoopSource* source) = 0; - virtual bool DoRemoveSource(wxAbstractEventLoopSource* source) = 0; - - wxEventLoopSourceHashSet m_sourceMap; -#endif - // this function should be called before the event loop terminates, whether // this happens normally (because of Exit() call) or abnormally (because of // an exception thrown from inside the loop) @@ -479,18 +228,31 @@ private: #endif // platforms using "manual" loop +// include the header defining wxConsoleEventLoop for Unix systems +#if defined(__UNIX__) + #include "wx/unix/evtloop.h" +#endif + // we're moving away from old m_impl wxEventLoop model as otherwise the user // code doesn't have access to platform-specific wxEventLoop methods and this // can sometimes be very useful (e.g. under MSW this is necessary for -// integration with MFC) but currently this is done for MSW only, other ports -// should follow a.s.a.p. +// integration with MFC) but currently this is not done for all ports yet (e.g. +// wxX11) so fall back to the old wxGUIEventLoop definition below for them + #if defined(__WXPALMOS__) #include "wx/palmos/evtloop.h" #elif defined(__WXMSW__) + // this header defines both console and GUI loops for MSW #include "wx/msw/evtloop.h" -#elif defined(__WXMAC__) +#elif defined(__WXOSX__) + // CoreFoundation-based event loop is currently in wxBase so include it in + // any case too (although maybe it actually shouldn't be there at all) #include "wx/osx/evtloop.h" -#elif defined(__WXCOCOA__) +#elif wxUSE_GUI + +// include the appropriate header defining wxGUIEventLoop + +#if defined(__WXCOCOA__) #include "wx/cocoa/evtloop.h" #elif defined(__WXDFB__) #include "wx/dfb/evtloop.h" @@ -538,16 +300,13 @@ protected: #endif // platforms -// also include the header defining wxConsoleEventLoop for Unix systems -#if defined(__UNIX__) - #include "wx/unix/evtloop.h" -#endif +#endif // wxUSE_GUI -// we use a class rather than a typedef because wxEventLoop is forward-declared -// in many places #if wxUSE_GUI + // we use a class rather than a typedef because wxEventLoop is + // forward-declared in many places class wxEventLoop : public wxGUIEventLoop { }; -#else // !GUI +#else // !wxUSE_GUI // we can't define wxEventLoop differently in GUI and base libraries so use // a #define to still allow writing wxEventLoop in the user code #if wxUSE_CONSOLE_EVENTLOOP && (defined(__WXMSW__) || defined(__UNIX__)) diff --git a/include/wx/evtloopsrc.h b/include/wx/evtloopsrc.h new file mode 100644 index 0000000000..b626bdff4c --- /dev/null +++ b/include/wx/evtloopsrc.h @@ -0,0 +1,99 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/evtloopsrc.h +// Purpose: declaration of wxEventLoopSource class +// Author: Vadim Zeitlin +// Created: 2009-10-21 +// RCS-ID: $Id: wxhead.h,v 1.11 2009-06-29 10:23:04 zeitlin Exp $ +// Copyright: (c) 2009 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_EVTLOOPSRC_H_ +#define _WX_EVTLOOPSRC_H_ + +// ---------------------------------------------------------------------------- +// wxEventLoopSource: a source of events which may be added to wxEventLoop +// ---------------------------------------------------------------------------- + +// TODO: refactor wxSocket under Unix to reuse wxEventLoopSource instead of +// duplicating much of its logic +// +// TODO: freeze the API and document it + +#if wxUSE_EVENTLOOP_SOURCE + +#define wxTRACE_EVT_SOURCE "EventSource" + +// handler used to process events on event loop sources +class wxEventLoopSourceHandler +{ +public: + // called when descriptor is available for non-blocking read + virtual void OnReadWaiting() = 0; + + // called when descriptor is available for non-blocking write + virtual void OnWriteWaiting() = 0; + + // called when there is exception on descriptor + virtual void OnExceptionWaiting() = 0; + + // virtual dtor for the base class + virtual ~wxEventLoopSourceHandler() { } +}; + +// flags describing which kind of IO events we're interested in +enum +{ + wxEVENT_SOURCE_INPUT = 0x01, + wxEVENT_SOURCE_OUTPUT = 0x02, + wxEVENT_SOURCE_EXCEPTION = 0x04, + wxEVENT_SOURCE_ALL = wxEVENT_SOURCE_INPUT | + wxEVENT_SOURCE_OUTPUT | + wxEVENT_SOURCE_EXCEPTION, +}; + +// wxEventLoopSource itself is an ABC and can't be created directly, currently +// the only way to create it is by using wxEventLoop::AddSourceForFD(). +class wxEventLoopSource +{ +public: + // dtor is pure virtual because it must be overridden to remove the source + // from the event loop monitoring it + virtual ~wxEventLoopSource() = 0; + + void SetHandler(wxEventLoopSourceHandler* handler) { m_handler = handler; } + wxEventLoopSourceHandler* GetHandler() const { return m_handler; } + + void SetFlags(int flags) { m_flags = flags; } + int GetFlags() const { return m_flags; } + +protected: + // ctor is only used by the derived classes + wxEventLoopSource(wxEventLoopSourceHandler *handler, int flags) + : m_handler(handler), + m_flags(flags) + { + } + + wxEventLoopSourceHandler* m_handler; + int m_flags; + + wxDECLARE_NO_COPY_CLASS(wxEventLoopSource); +}; + +inline wxEventLoopSource::~wxEventLoopSource() { } + +#if defined(__UNIX__) + #include "wx/unix/evtloopsrc.h" +#endif // __UNIX__ + +#if defined(__WXGTK20__) + #include "wx/gtk/evtloopsrc.h" +#elif defined(__WXOSX__) + #include "wx/osx/evtloopsrc.h" +#endif // platform + +#endif // wxUSE_EVENTLOOP_SOURCE + +#endif // _WX_EVTLOOPSRC_H_ + diff --git a/include/wx/gtk/evtloop.h b/include/wx/gtk/evtloop.h index d6e632fa7c..d083567862 100644 --- a/include/wx/gtk/evtloop.h +++ b/include/wx/gtk/evtloop.h @@ -17,17 +17,9 @@ typedef union _GdkEvent GdkEvent; -#if wxUSE_EVENTLOOP_SOURCE -// maps event loop sources to gtk source ids -WX_DECLARE_HASH_MAP(wxUnixEventLoopSource*, int, wxPointerHash, wxPointerEqual, - wxEventLoopSourceIdMap); -#endif - -class WXDLLIMPEXP_BASE wxGUIEventLoop : public wxEventLoopBase +class WXDLLIMPEXP_CORE wxGUIEventLoop : public wxEventLoopBase { public: - typedef wxUnixEventLoopSource Source; - wxGUIEventLoop(); virtual int Run(); @@ -38,33 +30,15 @@ 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); } -#if wxUSE_EVENTLOOP_SOURCE - virtual wxUnixEventLoopSource* CreateSource() const - { - return new wxUnixEventLoopSource(); - } - - virtual wxUnixEventLoopSource* CreateSource(int res, - wxEventLoopSourceHandler* handler, - int flags) const - { - return new wxUnixEventLoopSource(res, handler, flags); - } -#endif - -protected: -#if wxUSE_EVENTLOOP_SOURCE - // adding/removing sources - virtual bool DoAddSource(wxAbstractEventLoopSource* source); - virtual bool DoRemoveSource(wxAbstractEventLoopSource* source); - - // map of event loop sources gtk ids - wxEventLoopSourceIdMap m_sourceIdMap; -#endif - +private: // the exit code of this event loop int m_exitcode; diff --git a/include/wx/gtk/evtloopsrc.h b/include/wx/gtk/evtloopsrc.h new file mode 100644 index 0000000000..11ab82a827 --- /dev/null +++ b/include/wx/gtk/evtloopsrc.h @@ -0,0 +1,40 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/gtk/evtloopsrc.h +// Purpose: wxGTKEventLoopSource class +// Author: Vadim Zeitlin +// Created: 2009-10-21 +// RCS-ID: $Id: wxhead.h,v 1.11 2009-06-29 10:23:04 zeitlin Exp $ +// Copyright: (c) 2009 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_GTK_EVTLOOPSRC_H_ +#define _WX_GTK_EVTLOOPSRC_H_ + +// ---------------------------------------------------------------------------- +// wxGTKEventLoopSource: wxEventLoopSource for GTK port +// ---------------------------------------------------------------------------- + +class wxGTKEventLoopSource : public wxEventLoopSource +{ +public: + // sourceId is the id of the watch in GTK context, not the FD of the file + // this source corresponds to + wxGTKEventLoopSource(unsigned sourceId, + wxEventLoopSourceHandler *handler, + int flags) + : wxEventLoopSource(handler, flags), + m_sourceId(sourceId) + { + } + + virtual ~wxGTKEventLoopSource(); + +private: + const unsigned m_sourceId; + + wxDECLARE_NO_COPY_CLASS(wxGTKEventLoopSource); +}; + +#endif // _WX_GTK_EVTLOOPSRC_H_ + diff --git a/include/wx/osx/carbon/evtloop.h b/include/wx/osx/carbon/evtloop.h index d704a9c50c..e6d29419d6 100644 --- a/include/wx/osx/carbon/evtloop.h +++ b/include/wx/osx/carbon/evtloop.h @@ -15,7 +15,7 @@ class OpaqueEventRef; typedef OpaqueEventRef *EventRef; -class WXDLLIMPEXP_CORE wxGUIEventLoop : public wxEventLoopManual +class WXDLLIMPEXP_CORE wxGUIEventLoop : public wxCFEventLoop { public: wxGUIEventLoop(); @@ -28,6 +28,9 @@ public: virtual void WakeUp(); virtual bool YieldFor(long eventsToProcess); +protected: + virtual CFRunLoopRef CFGetCurrentRunLoop() const; + private: // dispatch an event and release it void DispatchAndReleaseEvent(EventRef event); diff --git a/include/wx/osx/cocoa/evtloop.h b/include/wx/osx/cocoa/evtloop.h index 63c565721c..8fc7c33258 100644 --- a/include/wx/osx/cocoa/evtloop.h +++ b/include/wx/osx/cocoa/evtloop.h @@ -11,11 +11,9 @@ #ifndef _WX_OSX_COCOA_EVTLOOP_H_ #define _WX_OSX_COCOA_EVTLOOP_H_ -class WXDLLIMPEXP_BASE wxGUIEventLoop : public wxEventLoopManual +class WXDLLIMPEXP_BASE wxGUIEventLoop : public wxCFEventLoop { public: - typedef wxMacEventLoopSource Source; - wxGUIEventLoop(); // implement/override base class pure virtual @@ -26,30 +24,8 @@ public: virtual void WakeUp(); virtual bool YieldFor(long eventsToProcess); -#if wxUSE_EVENTLOOP_SOURCE - virtual wxMacEventLoopSource* CreateSource() const - { - return new wxMacEventLoopSource(); - } - - virtual wxMacEventLoopSource* CreateSource(int res, - wxEventLoopSourceHandler* handler, - int flags) const; - - virtual wxMacEventLoopSource* CreateSource(CFRunLoopSourceRef res, - wxEventLoopSourceHandler* handler, - int flags) const - { - return new wxMacEventLoopSource(res, handler, flags); - } -#endif - protected: -#if wxUSE_EVENTLOOP_SOURCE - // adding/removing sources - virtual bool DoAddSource(wxAbstractEventLoopSource* source); - virtual bool DoRemoveSource(wxAbstractEventLoopSource* source); -#endif + virtual CFRunLoopRef CFGetCurrentRunLoop() const; private: double m_sleepTime; diff --git a/include/wx/osx/core/cfref.h b/include/wx/osx/core/cfref.h index f5251ab1c0..eb6adeeee0 100644 --- a/include/wx/osx/core/cfref.h +++ b/include/wx/osx/core/cfref.h @@ -308,6 +308,15 @@ public: wxCFRelease(m_ptr); m_ptr = p; // Automatic conversion should occur } + + // Release the pointer, i.e. give up its ownership. + refType release() + { + refType p = m_ptr; + m_ptr = NULL; + return p; + } + protected: /*! @var m_ptr The raw pointer. */ diff --git a/include/wx/osx/evtloop.h b/include/wx/osx/evtloop.h index 7b1b1f5f5d..a295706f58 100644 --- a/include/wx/osx/evtloop.h +++ b/include/wx/osx/evtloop.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////// -// Name: include/wx/mac/evtloop.h +// Name: include/wx/osx/evtloop.h // Purpose: simply forwards to wx/mac/carbon/evtloop.h for consistency with // the other Mac headers // Author: Vadim Zeitlin @@ -10,9 +10,30 @@ // Licence: wxWindows licence /////////////////////////////////////////////////////////////////////////////// -#ifdef __WXOSX_COCOA__ - #include "wx/osx/cocoa/evtloop.h" -#else - #include "wx/osx/carbon/evtloop.h" -#endif +#ifndef _WX_OSX_EVTLOOP_H_ +#define _WX_OSX_EVTLOOP_H_ +typedef struct __CFRunLoop * CFRunLoopRef; + +class WXDLLIMPEXP_BASE wxCFEventLoop : public wxEventLoopManual +{ +public: +#if wxUSE_EVENTLOOP_SOURCE + virtual wxEventLoopSource * + AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags); +#endif // wxUSE_EVENTLOOP_SOURCE + +protected: + // get the currently executing CFRunLoop + virtual CFRunLoopRef CFGetCurrentRunLoop() const = 0; +}; + +#if wxUSE_GUI + #ifdef __WXOSX_COCOA__ + #include "wx/osx/cocoa/evtloop.h" + #else + #include "wx/osx/carbon/evtloop.h" + #endif +#endif // wxUSE_GUI + +#endif // _WX_OSX_EVTLOOP_H_ diff --git a/include/wx/osx/evtloopsrc.h b/include/wx/osx/evtloopsrc.h new file mode 100644 index 0000000000..22ab30a5ad --- /dev/null +++ b/include/wx/osx/evtloopsrc.h @@ -0,0 +1,41 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/osx/evtloopsrc.h +// Purpose: wxCFEventLoopSource class +// Author: Vadim Zeitlin +// Created: 2009-10-21 +// RCS-ID: $Id: wxhead.h,v 1.11 2009-06-29 10:23:04 zeitlin Exp $ +// Copyright: (c) 2009 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_OSX_EVTLOOPSRC_H_ +#define _WX_OSX_EVTLOOPSRC_H_ + +typedef struct __CFFileDescriptor *CFFileDescriptorRef; + +// ---------------------------------------------------------------------------- +// wxCFEventLoopSource: CoreFoundation-based wxEventLoopSource for OS X +// ---------------------------------------------------------------------------- + +class wxCFEventLoopSource : public wxEventLoopSource +{ +public: + wxCFEventLoopSource(wxEventLoopSourceHandler *handler, int flags) + : wxEventLoopSource(handler, flags) + { + m_cffd = NULL; + } + + // we take ownership of this CFFileDescriptorRef + void SetFileDescriptor(CFFileDescriptorRef cffd); + + virtual ~wxCFEventLoopSource(); + +private: + CFFileDescriptorRef m_cffd; + + wxDECLARE_NO_COPY_CLASS(wxCFEventLoopSource); +}; + +#endif // _WX_OSX_EVTLOOPSRC_H_ + diff --git a/include/wx/private/fswatcher.h b/include/wx/private/fswatcher.h index 286fba8547..d10b4036da 100644 --- a/include/wx/private/fswatcher.h +++ b/include/wx/private/fswatcher.h @@ -52,7 +52,7 @@ public: wxCHECK_MSG( m_watches.find(winfo.GetPath()) == m_watches.end(), false, "Path '%s' is already watched"); - // conctruct watch entry + // construct watch entry wxSharedPtr watch(new wxFSWatchEntry(winfo)); if (!DoAdd(watch)) diff --git a/include/wx/unix/evtloop.h b/include/wx/unix/evtloop.h index 35d918390c..40d3007787 100644 --- a/include/wx/unix/evtloop.h +++ b/include/wx/unix/evtloop.h @@ -1,4 +1,4 @@ - /////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// // Name: wx/unix/evtloop.h // Purpose: declares wxEventLoop class // Author: Lukasz Michalski (lm@zork.pl) @@ -18,6 +18,7 @@ // ---------------------------------------------------------------------------- class wxFDIODispatcher; +class wxUnixEventLoopSource; namespace wxPrivate { @@ -27,8 +28,6 @@ namespace wxPrivate class WXDLLIMPEXP_BASE wxConsoleEventLoop : public wxEventLoopManual { public: - typedef wxUnixEventLoopSource Source; - // initialize the event loop, use IsOk() to check if we were successful wxConsoleEventLoop(); virtual ~wxConsoleEventLoop(); @@ -42,26 +41,11 @@ public: virtual bool YieldFor(long WXUNUSED(eventsToProcess)) { return true; } #if wxUSE_EVENTLOOP_SOURCE - virtual wxUnixEventLoopSource* CreateSource() const - { - return new wxUnixEventLoopSource(); - } - - virtual wxUnixEventLoopSource* CreateSource(int res, - wxEventLoopSourceHandler* handler, - int flags) const - { - return new wxUnixEventLoopSource(res, handler, flags); - } -#endif + virtual wxEventLoopSource * + AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags); +#endif // wxUSE_EVENTLOOP_SOURCE protected: -#if wxUSE_EVENTLOOP_SOURCE - // adding/removing sources - virtual bool DoAddSource(wxAbstractEventLoopSource* source); - virtual bool DoRemoveSource(wxAbstractEventLoopSource* source); -#endif - virtual void OnNextIteration(); private: diff --git a/include/wx/unix/evtloopsrc.h b/include/wx/unix/evtloopsrc.h new file mode 100644 index 0000000000..20e2762758 --- /dev/null +++ b/include/wx/unix/evtloopsrc.h @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/unix/evtloopsrc.h +// Purpose: wxUnixEventLoopSource class +// Author: Vadim Zeitlin +// Created: 2009-10-21 +// RCS-ID: $Id: wxhead.h,v 1.11 2009-06-29 10:23:04 zeitlin Exp $ +// Copyright: (c) 2009 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_UNIX_EVTLOOPSRC_H_ +#define _WX_UNIX_EVTLOOPSRC_H_ + +class wxFDIODispatcher; +class wxFDIOHandler; + +// ---------------------------------------------------------------------------- +// wxUnixEventLoopSource: wxEventLoopSource for Unix-like toolkits using fds +// ---------------------------------------------------------------------------- + +class wxUnixEventLoopSource : public wxEventLoopSource +{ +public: + // dispatcher and fdioHandler are only used here to allow us to unregister + // from the event loop when we're destroyed + wxUnixEventLoopSource(wxFDIODispatcher *dispatcher, + wxFDIOHandler *fdioHandler, + int fd, + wxEventLoopSourceHandler *handler, + int flags) + : wxEventLoopSource(handler, flags), + m_dispatcher(dispatcher), + m_fdioHandler(fdioHandler), + m_fd(fd) + { + } + + virtual ~wxUnixEventLoopSource(); + +private: + wxFDIODispatcher * const m_dispatcher; + wxFDIOHandler * const m_fdioHandler; + const int m_fd; + + wxDECLARE_NO_COPY_CLASS(wxUnixEventLoopSource); +}; + +#endif // _WX_UNIX_EVTLOOPSRC_H_ + diff --git a/include/wx/unix/private/fswatcher_inotify.h b/include/wx/unix/private/fswatcher_inotify.h index ea6f8886c3..56ab35892a 100644 --- a/include/wx/unix/private/fswatcher_inotify.h +++ b/include/wx/unix/private/fswatcher_inotify.h @@ -12,6 +12,7 @@ #define WX_UNIX_PRIVATE_FSWATCHER_INOTIFY_H_ #include "wx/filename.h" +#include "wx/evtloopsrc.h" // ============================================================================ // wxFSWatcherEntry implementation & helper declarations diff --git a/include/wx/unix/private/fswatcher_kqueue.h b/include/wx/unix/private/fswatcher_kqueue.h index 1b56887b8e..181c37531f 100644 --- a/include/wx/unix/private/fswatcher_kqueue.h +++ b/include/wx/unix/private/fswatcher_kqueue.h @@ -106,29 +106,4 @@ private: wxDECLARE_NO_COPY_CLASS(wxFSWatchEntryKq); }; - -// ============================================================================ -// wxFSWSourceHandler helper class -// ============================================================================ - -class wxFSWatcherImplKqueue; - -/** - * Handler for handling i/o from inotify descriptor - */ -class wxFSWSourceHandler : public wxEventLoopSourceHandler -{ -public: - wxFSWSourceHandler(wxFSWatcherImplKqueue* service) : - m_service(service) - { } - - virtual void OnReadWaiting(); - virtual void OnWriteWaiting(); - virtual void OnExceptionWaiting(); - -protected: - wxFSWatcherImplKqueue* m_service; -}; - #endif /* WX_UNIX_PRIVATE_FSWATCHER_KQUEUE_H_ */ diff --git a/samples/fswatcher/fswatcher.cpp b/samples/fswatcher/fswatcher.cpp index 51014172df..7b30d4212e 100644 --- a/samples/fswatcher/fswatcher.cpp +++ b/samples/fswatcher/fswatcher.cpp @@ -66,8 +66,7 @@ public: // 'Main program' equivalent: the program execution "starts" here virtual bool OnInit() { - // TODO remove then this code becomes rock-solid - wxLog::AddTraceMask(wxTRACE_EVT_SOURCE); + wxLog::AddTraceMask("EventSource"); wxLog::AddTraceMask(wxTRACE_FSWATCHER); // create the main application window diff --git a/src/common/evtloopcmn.cpp b/src/common/evtloopcmn.cpp index 9b72655106..5f9894d125 100644 --- a/src/common/evtloopcmn.cpp +++ b/src/common/evtloopcmn.cpp @@ -54,11 +54,6 @@ void wxEventLoopBase::OnExit() { if (wxTheApp) wxTheApp->OnEventLoopExit(this); - -#if wxUSE_EVENTLOOP_SOURCE - // unregister all sources - (void) RemoveAllSources(); -#endif } void wxEventLoopBase::WakeUpIdle() diff --git a/src/gtk/evtloop.cpp b/src/gtk/evtloop.cpp index 9d43d56d9e..1c656d5661 100644 --- a/src/gtk/evtloop.cpp +++ b/src/gtk/evtloop.cpp @@ -25,6 +25,7 @@ #endif #include "wx/evtloop.h" +#include "wx/evtloopsrc.h" #ifndef WX_PRECOMP #include "wx/app.h" @@ -86,49 +87,40 @@ void wxGUIEventLoop::WakeUp() // wxEventLoop adding & removing sources // ---------------------------------------------------------------------------- +#if wxUSE_EVENTLOOP_SOURCE + extern "C" { static gboolean wx_on_channel_event(GIOChannel *channel, - GIOCondition condition, gpointer data) + GIOCondition condition, + gpointer data) { - wxLogTrace(wxTRACE_EVT_SOURCE, "wx_on_channel_event, gtk_source_id=%d", - g_io_channel_unix_get_fd(channel)); + wxLogTrace(wxTRACE_EVT_SOURCE, + "wx_on_channel_event, fd=%d, condition=%08x", + g_io_channel_unix_get_fd(channel), condition); - wxEventLoopSourceHandler* handler = - static_cast(data); + wxEventLoopSourceHandler * const + handler = static_cast(data); if (condition & G_IO_IN || condition & G_IO_PRI) - { handler->OnReadWaiting(); - } - else if (condition & G_IO_OUT) - { + if (condition & G_IO_OUT) handler->OnWriteWaiting(); - } else if (condition & G_IO_ERR || condition & G_IO_NVAL) - { handler->OnExceptionWaiting(); - } - else - { - wxFAIL_MSG(wxString::Format("Inavlid condition=%d", condition)); - } // we never want to remove source here, so always return true return TRUE; } } -bool wxGUIEventLoop::DoAddSource(wxAbstractEventLoopSource* src) +wxEventLoopSource * +wxGUIEventLoop::AddSourceForFD(int fd, + wxEventLoopSourceHandler *handler, + int flags) { - Source* source = dynamic_cast(src); - wxCHECK_MSG( source, false, "Invalid source type" ); + wxCHECK_MSG( fd != -1, NULL, "can't monitor invalid fd" ); - wxLogTrace(wxTRACE_EVT_SOURCE, - "wxGUIEventLoop::DoAddSource() source=%d", - source->GetResource()); - - int flags = source->GetFlags(); int condition = 0; if (flags & wxEVENT_SOURCE_INPUT) condition |= G_IO_IN | G_IO_PRI; @@ -137,32 +129,38 @@ bool wxGUIEventLoop::DoAddSource(wxAbstractEventLoopSource* src) if (flags & wxEVENT_SOURCE_EXCEPTION) condition |= G_IO_ERR | G_IO_HUP | G_IO_NVAL; - GIOChannel* channel = g_io_channel_unix_new(source->GetResource()); - int gtk_id = g_io_add_watch(channel, (GIOCondition)condition, - &wx_on_channel_event, source->GetHandler()); + 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); - wxEventLoopSourceIdMap::value_type val(source, gtk_id); - return m_sourceIdMap.insert(val).second; -} - -bool wxGUIEventLoop::DoRemoveSource(wxAbstractEventLoopSource* src) -{ - Source* source = dynamic_cast(src); - wxCHECK_MSG( source, false, "Invalid source type" ); + if ( !sourceId ) + return NULL; wxLogTrace(wxTRACE_EVT_SOURCE, - "wxGUIEventLoop::DoRemoveSource() source=%d", - source->GetResource()); + "Adding event loop source for fd=%d with GTK id=%u", + fd, sourceId); - wxEventLoopSourceIdMap::iterator it = m_sourceIdMap.find(source); - wxCHECK_MSG( it != m_sourceIdMap.end(), false, "Source not on the list" ); - int gtk_id = it->second; - m_sourceIdMap.erase(it); - return g_source_remove(gtk_id); + return new wxGTKEventLoopSource(sourceId, handler, flags); } +wxGTKEventLoopSource::~wxGTKEventLoopSource() +{ + wxLogTrace(wxTRACE_EVT_SOURCE, + "Removing event loop source with GTK id=%u", m_sourceId); + + g_source_remove(m_sourceId); +} + +#endif // wxUSE_EVENTLOOP_SOURCE + // ---------------------------------------------------------------------------- // wxEventLoop message processing dispatching // ---------------------------------------------------------------------------- diff --git a/src/osx/carbon/evtloop.cpp b/src/osx/carbon/evtloop.cpp index cdfda0653d..928e7f90a7 100644 --- a/src/osx/carbon/evtloop.cpp +++ b/src/osx/carbon/evtloop.cpp @@ -49,6 +49,11 @@ void wxGUIEventLoop::WakeUp() wxMacWakeUp(); } +CFRunLoopRef wxGUIEventLoop::CFGetCurrentRunLoop() const +{ + return CFRunLoopGetCurrent(); +} + void wxGUIEventLoop::DispatchAndReleaseEvent(EventRef theEvent) { if ( wxTheApp ) diff --git a/src/osx/cocoa/evtloop.mm b/src/osx/cocoa/evtloop.mm index 78f7749d7e..4798214f02 100644 --- a/src/osx/cocoa/evtloop.mm +++ b/src/osx/cocoa/evtloop.mm @@ -87,102 +87,10 @@ void wxGUIEventLoop::WakeUp() wxMacWakeUp(); } -//----------------------------------------------------------------------------- -// event loop sources operations -//----------------------------------------------------------------------------- - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 -extern "C" +CFRunLoopRef wxGUIEventLoop::CFGetCurrentRunLoop() const { -struct wx_cffd_data -{ - wxEventLoopSourceHandler* handler; - int flags; -}; - -static void wx_cffiledescriptor_callback(CFFileDescriptorRef cffd, - CFOptionFlags flags, void* ctxData) -{ - wxLogTrace(wxTRACE_EVT_SOURCE, "CFFileDescriptor Callback"); - - wx_cffd_data* data = static_cast(ctxData); - wxEventLoopSourceHandler* handler = data->handler; - if (flags & kCFFileDescriptorReadCallBack) - handler->OnReadWaiting(); - if (flags & kCFFileDescriptorWriteCallBack) - handler->OnWriteWaiting(); - - // reenable callbacks - if (data->flags & wxEVENT_SOURCE_INPUT) - CFFileDescriptorEnableCallBacks(cffd, kCFFileDescriptorReadCallBack); - if (data->flags & wxEVENT_SOURCE_OUTPUT) - CFFileDescriptorEnableCallBacks(cffd, kCFFileDescriptorWriteCallBack); -} -} - -wxMacEventLoopSource* wxGUIEventLoop::CreateSource(int fd, - wxEventLoopSourceHandler* handler, - int flags) const -{ - wxMacEventLoopSource* source = new wxMacEventLoopSource(); - // FIXME this is currently a leak :-) - wx_cffd_data* data = new wx_cffd_data; - data->handler = handler; - data->flags = flags; - CFFileDescriptorContext ctx = { 0, data, NULL, NULL, NULL }; - CFFileDescriptorRef cffd = CFFileDescriptorCreate(kCFAllocatorDefault, fd, - true, wx_cffiledescriptor_callback, &ctx); - - if (flags & wxEVENT_SOURCE_INPUT) - CFFileDescriptorEnableCallBacks(cffd, kCFFileDescriptorReadCallBack); - if (flags & wxEVENT_SOURCE_OUTPUT) - CFFileDescriptorEnableCallBacks(cffd, kCFFileDescriptorWriteCallBack); - - source->SetResource( - CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, cffd, 0)); - source->SetHandler(handler); - source->SetFlags(flags); - return source; -} -#elif -wxMacEventLoopSource* wxGUIEventLoop::CreateSource(int fd, - wxEventLoopSourceHandler* handler, - int flags) const -{ - return NULL; -} -#endif - -bool wxGUIEventLoop::DoAddSource(wxAbstractEventLoopSource* src) -{ - Source* source = dynamic_cast(src); - wxCHECK_MSG( source, false, "Invalid source type" ); - - wxLogTrace(wxTRACE_EVT_SOURCE, - "wxGUIEventLoop::AddSource() source=%d", - source->GetResource()); - NSRunLoop* nsloop = [NSRunLoop currentRunLoop]; - CFRunLoopRef cfloop = [nsloop getCFRunLoop]; - CFRunLoopAddSource(cfloop, source->GetResource(), kCFRunLoopDefaultMode); - - return true; -} - -bool wxGUIEventLoop::DoRemoveSource(wxAbstractEventLoopSource* src) -{ - Source* source = dynamic_cast(src); - wxCHECK_MSG( source, false, "Invalid source type" ); - - wxLogTrace(wxTRACE_EVT_SOURCE, - "wxGUIEventLoop::RemoveSource() source=%d", - source->GetResource()); - - NSRunLoop* nsloop = [NSRunLoop currentRunLoop]; - CFRunLoopRef cfloop = [nsloop getCFRunLoop]; - CFRunLoopRemoveSource(cfloop, source->GetResource(), kCFRunLoopDefaultMode); - - return true; + return [nsloop getCFRunLoop]; } //----------------------------------------------------------------------------- diff --git a/src/osx/core/evtloop_cf.cpp b/src/osx/core/evtloop_cf.cpp new file mode 100644 index 0000000000..a0e30982c4 --- /dev/null +++ b/src/osx/core/evtloop_cf.cpp @@ -0,0 +1,138 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: src/osx/core/evtloop_cf.cpp +// Purpose: wxEventLoop implementation common to both Carbon and Cocoa +// Author: Vadim Zeitlin +// Created: 2009-10-18 +// RCS-ID: $Id: wxhead.cpp,v 1.10 2009-06-29 10:23:04 zeitlin Exp $ +// Copyright: (c) 2009 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +// for compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#include "wx/evtloop.h" + +#if wxUSE_EVENTLOOP_SOURCE + +#include "wx/evtloopsrc.h" + +#include "wx/scopedptr.h" + +#include "wx/osx/private.h" +#include "wx/osx/core/cfref.h" + +// ============================================================================ +// wxCFEventLoopSource and wxCFEventLoop implementation +// ============================================================================ + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +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; + + source->SetFileDescriptor(cffd.release()); + + wxCFRef + cfsrc(CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, cffd, 0)); + if ( !cfsrc ) + return NULL; + + CFRunLoopRef cfloop = CFGetCurrentRunLoop(); + CFRunLoopAddSource(cfloop, cfsrc, kCFRunLoopDefaultMode); + + return source.release(); +} + +void wxCFEventLoopSource::SetFileDescriptor(CFFileDescriptorRef cffd) +{ + wxASSERT_MSG( !m_cffd, "shouldn't be called more than once" ); + + m_cffd = cffd; +} + +wxCFEventLoopSource::~wxCFEventLoopSource() +{ + if ( m_cffd ) + CFRelease(m_cffd); +} + +#else // OS X < 10.5 + +wxEventLoopSource * +wxCFEventLoop::AddSourceForFD(int WXUNUSED(fd), + wxEventLoopSourceHandler * WXUNUSED(handler), + int WXUNUSED(flags)) +{ + return NULL; +} + +#endif // MAC_OS_X_VERSION_MAX_ALLOWED + +#endif // wxUSE_EVENTLOOP_SOURCE diff --git a/src/unix/evtloopunix.cpp b/src/unix/evtloopunix.cpp index b082984019..453f1c354a 100644 --- a/src/unix/evtloopunix.cpp +++ b/src/unix/evtloopunix.cpp @@ -30,6 +30,7 @@ #include #include "wx/apptrait.h" +#include "wx/scopedptr.h" #include "wx/thread.h" #include "wx/module.h" #include "wx/unix/pipe.h" @@ -37,6 +38,10 @@ #include "wx/unix/private/epolldispatcher.h" #include "wx/private/selectdispatcher.h" +#if wxUSE_EVENTLOOP_SOURCE + #include "wx/evtloopsrc.h" +#endif // wxUSE_EVENTLOOP_SOURCE + #define TRACE_EVENTS wxT("events") // =========================================================================== @@ -220,36 +225,40 @@ protected: wxEventLoopSourceHandler* m_impl; }; -bool wxConsoleEventLoop::DoAddSource(wxAbstractEventLoopSource* src) +wxEventLoopSource * +wxConsoleEventLoop::AddSourceForFD(int fd, + wxEventLoopSourceHandler *handler, + int flags) { - Source* source = dynamic_cast(src); - wxCHECK_MSG( source, false, "Invalid source type" ); + wxCHECK_MSG( fd != -1, NULL, "can't monitor invalid fd" ); wxLogTrace(wxTRACE_EVT_SOURCE, - "wxConsoleEventLoop::AddSource() source=%d", - source->GetResource()); + "Adding event loop source for fd=%d", fd); - // translating into wxFDIOHandler - // XXX this is a memory leak of course, but this is really temporary, so - // we are not creating another map of handlers - wxFDIOHandler* h = new wxFDIOEventLoopSourceHandler(source->GetHandler()); + // we need a bridge to wxFDIODispatcher + // + // TODO: refactor the code so that only wxEventLoopSourceHandler is used + wxScopedPtr + fdioHandler(new wxFDIOEventLoopSourceHandler(handler)); - return m_dispatcher->RegisterFD(source->GetResource(), h, - source->GetFlags()); + if ( !m_dispatcher->RegisterFD(fd, fdioHandler.get(), flags) ) + return NULL; + + return new wxUnixEventLoopSource(m_dispatcher, fdioHandler.release(), + fd, handler, flags); } -bool wxConsoleEventLoop::DoRemoveSource(wxAbstractEventLoopSource* src) +wxUnixEventLoopSource::~wxUnixEventLoopSource() { - Source* source = dynamic_cast(src); - wxCHECK_MSG( source, false, "Invalid source type" ); - wxLogTrace(wxTRACE_EVT_SOURCE, - "wxConsoleEventLoop::RemoveSource() source=%d", - source->GetResource()); + "Removing event loop source for fd=%d", m_fd); - return m_dispatcher->UnregisterFD(source->GetResource()); + m_dispatcher->UnregisterFD(m_fd); + + delete m_fdioHandler; } -#endif + +#endif // wxUSE_EVENTLOOP_SOURCE //----------------------------------------------------------------------------- // events dispatch and loop handling diff --git a/src/unix/fswatcher_inotify.cpp b/src/unix/fswatcher_inotify.cpp index 229af98eee..edb3c52765 100644 --- a/src/unix/fswatcher_inotify.cpp +++ b/src/unix/fswatcher_inotify.cpp @@ -45,8 +45,8 @@ class wxFSWatcherImplUnix : public wxFSWatcherImpl public: wxFSWatcherImplUnix(wxFileSystemWatcherBase* watcher) : wxFSWatcherImpl(watcher), - m_loop(NULL), - m_source(NULL) + m_source(NULL), + m_ifd(-1) { m_handler = new wxFSWSourceHandler(this); } @@ -65,42 +65,39 @@ public: bool Init() { wxCHECK_MSG( !IsOk(), false, "Inotify already initialized" ); - wxCHECK_MSG( m_loop == NULL, false, "Event loop != NULL"); - m_loop = (wxEventLoopBase::GetActive()); - wxCHECK_MSG( m_loop, false, "File system watcher needs an active loop" ); + wxEventLoopBase *loop = wxEventLoopBase::GetActive(); + wxCHECK_MSG( loop, false, "File system watcher needs an event loop" ); - int fd = inotify_init(); - if (fd == -1) + m_ifd = inotify_init(); + if ( m_ifd == -1 ) { wxLogSysError( _("Unable to create inotify instance") ); return false; } - int flags = wxEVENT_SOURCE_INPUT | wxEVENT_SOURCE_EXCEPTION; - m_source = static_cast( - m_loop->CreateSource(fd, m_handler, flags)); - return RegisterSource(); + m_source = loop->AddSourceForFD + ( + m_ifd, + m_handler, + wxEVENT_SOURCE_INPUT | wxEVENT_SOURCE_EXCEPTION + ); + + return m_source != NULL; } - bool Close() + void Close() { - wxCHECK_MSG( IsOk(), false, + wxCHECK_RET( IsOk(), "Inotify not initialized or invalid inotify descriptor" ); - wxCHECK_MSG( m_loop, false, - "m_loop shouldn't be null if inotify is initialized" ); - // ignore errors - (void) UnregisterSource(); + delete m_source; + m_source = NULL; - int ret = close(m_source->GetResource()); - if (ret == -1) + if ( close(m_ifd) != 0 ) { wxLogSysError( _("Unable to close inotify instance") ); } - m_source->Invalidate(); - - return ret != -1; } virtual bool DoAdd(wxSharedPtr watch) @@ -193,39 +190,16 @@ public: return event_count; } - bool IsOk() + bool IsOk() const { - return m_source && m_source->IsOk(); + return m_source != NULL; } protected: - bool RegisterSource() - { - wxCHECK_MSG( IsOk(), false, - "Inotify not initialized or invalid inotify descriptor" ); - - bool ret = m_loop->AddSource(m_source); - return ret; - } - - bool UnregisterSource() - { - wxCHECK_MSG( IsOk(), false, - "Inotify not initialized or invalid inotify descriptor" ); - wxCHECK_MSG( m_loop, false, - "m_loop shouldn't be null if inotify is initialized" ); - - bool ret = m_loop->RemoveSource(m_source); - m_loop = NULL; - return ret; - } - int DoAddInotify(wxFSWatchEntry* watch) { int flags = Watcher2NativeFlags(watch->GetFlags()); - int wd = inotify_add_watch(m_source->GetResource(), - watch->GetPath().fn_str(), - flags); + int wd = inotify_add_watch(m_ifd, watch->GetPath().fn_str(), flags); // finally we can set watch descriptor watch->SetWatchDescriptor(wd); return wd; @@ -233,8 +207,7 @@ protected: int DoRemoveInotify(wxFSWatchEntry* watch) { - return inotify_rm_watch(m_source->GetResource(), - watch->GetWatchDescriptor()); + return inotify_rm_watch(m_ifd, watch->GetWatchDescriptor()); } void ProcessNativeEvent(const inotify_event& inevt) @@ -352,7 +325,7 @@ protected: "Inotify not initialized or invalid inotify descriptor" ); memset(buf, 0, size); - ssize_t left = read(m_source->GetResource(), buf, size); + ssize_t left = read(m_ifd, buf, size); if (left == -1) { wxLogSysError(_("Unable to read from inotify descriptor")); @@ -451,8 +424,10 @@ protected: wxFSWSourceHandler* m_handler; // handler for inotify event source wxFSWatchEntryDescriptors m_watchMap; // inotify wd=>wxFSWatchEntry* map wxInotifyCookies m_cookies; // map to track renames - wxEventLoopBase* m_loop; - wxUnixEventLoopSource* m_source; // our event loop source + wxEventLoopSource* m_source; // our event loop source + + // file descriptor created by inotify_init() + int m_ifd; }; diff --git a/src/unix/fswatcher_kqueue.cpp b/src/unix/fswatcher_kqueue.cpp index ccadcb6090..e1046e2ea4 100644 --- a/src/unix/fswatcher_kqueue.cpp +++ b/src/unix/fswatcher_kqueue.cpp @@ -23,9 +23,37 @@ #include #include + #include "wx/dynarray.h" +#include "wx/evtloop.h" +#include "wx/evtloopsrc.h" + #include "wx/private/fswatcher.h" +// ============================================================================ +// wxFSWSourceHandler helper class +// ============================================================================ + +class wxFSWatcherImplKqueue; + +/** + * Handler for handling i/o from inotify descriptor + */ +class wxFSWSourceHandler : public wxEventLoopSourceHandler +{ +public: + wxFSWSourceHandler(wxFSWatcherImplKqueue* service) : + m_service(service) + { } + + virtual void OnReadWaiting(); + virtual void OnWriteWaiting(); + virtual void OnExceptionWaiting(); + +protected: + wxFSWatcherImplKqueue* m_service; +}; + // ============================================================================ // wxFSWatcherImpl implementation & helper wxFSWSourceHandler implementation // ============================================================================ @@ -38,14 +66,13 @@ class wxFSWatcherImplKqueue : public wxFSWatcherImpl public: wxFSWatcherImplKqueue(wxFileSystemWatcherBase* watcher) : wxFSWatcherImpl(watcher), - m_loop(NULL), m_source(NULL), m_kfd(-1) { m_handler = new wxFSWSourceHandler(this); } - ~wxFSWatcherImplKqueue() + virtual ~wxFSWatcherImplKqueue() { // we close kqueue only if initialized before if (IsOk()) @@ -60,10 +87,9 @@ public: { wxCHECK_MSG( !IsOk(), false, "Kqueue appears to be already initialized" ); - wxCHECK_MSG( m_loop == NULL, false, "Event loop != NULL"); - m_loop = (wxEventLoopBase::GetActive()); - wxCHECK_MSG( m_loop, false, "File system watcher needs an active loop" ); + wxEventLoopBase *loop = wxEventLoopBase::GetActive(); + wxCHECK_MSG( loop, false, "File system watcher needs an active loop" ); // create kqueue m_kfd = kqueue(); @@ -74,32 +100,23 @@ public: } // create source - int flags = wxEVENT_SOURCE_INPUT; - m_source = m_loop->CreateSource(m_kfd, m_handler, flags); - wxCHECK_MSG( m_source, false, - "Active loop has no support for fd-based sources" ); + m_source = loop->AddSourceForFD(m_kfd, m_handler, wxEVENT_SOURCE_INPUT); - return RegisterSource(); + return m_source != NULL; } - bool Close() + void Close() { - wxCHECK_MSG( IsOk(), false, + wxCHECK_RET( IsOk(), "Kqueue not initialized or invalid kqueue descriptor" ); - wxCHECK_MSG( m_loop, false, - "m_loop shouldn't be null if kqueue is initialized" ); - // ignore errors - (void) UnregisterSource(); - - int ret = close(m_kfd); - if (ret == -1) + if ( close(m_kfd) != 0 ) { - wxLogSysError(_("Unable to close kqueue instance")); + wxLogSysError(_("Error closing kqueue instance")); } - m_source->Invalidate(); - return ret != -1; + delete m_source; + m_source = NULL; } virtual bool DoAdd(wxSharedPtr watch) @@ -186,43 +203,18 @@ public: return true; } - bool IsOk() + bool IsOk() const { - return m_source && m_source->IsOk(); + return m_source != NULL; } -/* - wxAbstractEventLoopSource* GetSource() const - { - return m_source; - }*/ - protected: - bool RegisterSource() - { - wxCHECK_MSG( IsOk(), false, - "Kqueue not initialized or invalid kqueue descriptor" ); - - return m_loop->AddSource(m_source); - } - - bool UnregisterSource() - { - wxCHECK_MSG( IsOk(), false, - "Kqueue not initialized or invalid kqueue descriptor" ); - wxCHECK_MSG( m_loop, false, - "m_loop shouldn't be null if kqueue is initialized" ); - - bool ret = m_loop->RemoveSource(m_source); - m_loop = NULL; - return ret; - } - // returns all new dirs/files present in the immediate level of the dir // pointed by watch.GetPath(). "new" means created between the last time // the state of watch was computed and now - void FindChanges(wxFSWatchEntryKq& watch, wxArrayString& changedFiles, - wxArrayInt& changedFlags) + void FindChanges(wxFSWatchEntryKq& watch, + wxArrayString& changedFiles, + wxArrayInt& changedFlags) { wxFSWatchEntryKq::wxDirState old = watch.GetLastState(); watch.RefreshState(); @@ -386,8 +378,9 @@ protected: } wxFSWSourceHandler* m_handler; // handler for kqueue event source - wxEventLoopBase* m_loop; // event loop we have registered with - wxAbstractEventLoopSource* m_source; // our event loop source + wxEventLoopSource* m_source; // our event loop source + + // descriptor created by kqueue() int m_kfd; };