From 5cd99866132366b74289e5a08e963723732bae01 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 22 Oct 2009 11:36:35 +0000 Subject: [PATCH] Refactor wxEventLoopSource-related code. Currently wxEventLoopSource can't be created directly and can only be used to monitor file descriptors so reduce the API to just wxEventLoop::AddSourceForFD() and remove AddSource(), RemoveSource() and RemoveAllSources() which couldn't be implemented for all ports. This makes the code much simpler without any loss of functionality. Make wxEventLoopSource responsible for removing itself from the event loop when it is deleted. This allows to remove IsOk() and Invalidate() methods making the code simpler and gets rid of various sets/maps which were used before. This also allows to support event loop sources in Carbon as well: wxOSX/Carbon now compiles and works with wxUSE_FSWATCHER==1. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@62475 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- Makefile.in | 23 ++ build/bakefiles/files.bkl | 5 + include/wx/evtloop.h | 305 ++------------------ include/wx/evtloopsrc.h | 99 +++++++ include/wx/gtk/evtloop.h | 40 +-- include/wx/gtk/evtloopsrc.h | 40 +++ include/wx/osx/carbon/evtloop.h | 5 +- include/wx/osx/cocoa/evtloop.h | 28 +- include/wx/osx/core/cfref.h | 9 + include/wx/osx/evtloop.h | 33 ++- include/wx/osx/evtloopsrc.h | 41 +++ include/wx/private/fswatcher.h | 2 +- include/wx/unix/evtloop.h | 26 +- include/wx/unix/evtloopsrc.h | 49 ++++ include/wx/unix/private/fswatcher_inotify.h | 1 + include/wx/unix/private/fswatcher_kqueue.h | 25 -- samples/fswatcher/fswatcher.cpp | 3 +- src/common/evtloopcmn.cpp | 5 - src/gtk/evtloop.cpp | 80 +++-- src/osx/carbon/evtloop.cpp | 5 + src/osx/cocoa/evtloop.mm | 96 +----- src/osx/core/evtloop_cf.cpp | 138 +++++++++ src/unix/evtloopunix.cpp | 47 +-- src/unix/fswatcher_inotify.cpp | 81 ++---- src/unix/fswatcher_kqueue.cpp | 101 +++---- 25 files changed, 633 insertions(+), 654 deletions(-) create mode 100644 include/wx/evtloopsrc.h create mode 100644 include/wx/gtk/evtloopsrc.h create mode 100644 include/wx/osx/evtloopsrc.h create mode 100644 include/wx/unix/evtloopsrc.h create mode 100644 src/osx/core/evtloop_cf.cpp 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,209 +14,21 @@ #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; - } -#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; + class wxEventLoopSource; + class wxEventLoopSourceHandler; #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); - void StoreGdkEventForLaterProcessing(GdkEvent* ev) - { m_arrGdkEvents.Add(ev); } - #if wxUSE_EVENTLOOP_SOURCE - virtual wxUnixEventLoopSource* CreateSource() const - { - return new wxUnixEventLoopSource(); - } + virtual wxEventLoopSource * + AddSourceForFD(int fd, wxEventLoopSourceHandler *handler, int flags); +#endif // wxUSE_EVENTLOOP_SOURCE - 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 + void StoreGdkEventForLaterProcessing(GdkEvent* ev) + { m_arrGdkEvents.Add(ev); } +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; + if ( !sourceId ) + return NULL; + + wxLogTrace(wxTRACE_EVT_SOURCE, + "Adding event loop source for fd=%d with GTK id=%u", + fd, sourceId); + + + return new wxGTKEventLoopSource(sourceId, handler, flags); } -bool wxGUIEventLoop::DoRemoveSource(wxAbstractEventLoopSource* src) +wxGTKEventLoopSource::~wxGTKEventLoopSource() { - Source* source = dynamic_cast(src); - wxCHECK_MSG( source, false, "Invalid source type" ); - wxLogTrace(wxTRACE_EVT_SOURCE, - "wxGUIEventLoop::DoRemoveSource() source=%d", - source->GetResource()); + "Removing event loop source with GTK id=%u", m_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); + 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" -{ -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) +CFRunLoopRef wxGUIEventLoop::CFGetCurrentRunLoop() const { - 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; }; -- 2.45.2