Merge SOC2009_FSWATCHER branch into trunk.
Merges everything from the branch with only some minor changes, mostly renamed wxUSE_FSWATCHER_{INOTIFY,KQUEUE} to wxHAS_{INOTIFY,KQUEUE}. Add wxFileSystemWatcher and related classes. Also introduces wxEventLoopSource. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@62474 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -145,6 +145,14 @@
|
||||
# endif
|
||||
#endif /* !defined(wxUSE_FSVOLUME) */
|
||||
|
||||
#ifndef wxUSE_FSWATCHER
|
||||
# ifdef wxABORT_ON_CONFIG_ERROR
|
||||
# error "wxUSE_FSWATCHER must be defined, please read comment near the top of this file."
|
||||
# else
|
||||
# define wxUSE_FSWATCHER 0
|
||||
# endif
|
||||
#endif /* !defined(wxUSE_FSWATCHER) */
|
||||
|
||||
#ifndef wxUSE_DYNAMIC_LOADER
|
||||
# ifdef wxABORT_ON_CONFIG_ERROR
|
||||
# error "wxUSE_DYNAMIC_LOADER must be defined, please read comment near the top of this file."
|
||||
|
@@ -14,6 +14,208 @@
|
||||
|
||||
#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__))
|
||||
#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 T>
|
||||
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<CFRunLoopSourceRef>
|
||||
{
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
|
||||
int GetFileDescriptor() const
|
||||
{
|
||||
return m_fd;
|
||||
}
|
||||
#endif
|
||||
protected:
|
||||
wxMacEventLoopSource() : wxEventLoopSourceBase<CFRunLoopSourceRef>() { }
|
||||
|
||||
// ctor setting internal value to the os resource res
|
||||
wxMacEventLoopSource(CFRunLoopSourceRef res,
|
||||
wxEventLoopSourceHandler* handler, int flags) :
|
||||
wxEventLoopSourceBase<CFRunLoopSourceRef>(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<int>
|
||||
{
|
||||
protected:
|
||||
wxUnixEventLoopSource() : wxEventLoopSourceBase<int>() { }
|
||||
|
||||
// ctor setting internal value to the os resource res
|
||||
wxUnixEventLoopSource(int res, wxEventLoopSourceHandler* handler,
|
||||
int flags) :
|
||||
wxEventLoopSourceBase<int>(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
|
||||
@@ -64,6 +266,68 @@ public:
|
||||
// returns true if this is the main loop
|
||||
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
|
||||
|
||||
// dispatch&processing
|
||||
// -------------------
|
||||
@@ -114,25 +378,25 @@ public:
|
||||
// Yield-related hooks
|
||||
// -------------------
|
||||
|
||||
// process all currently pending events right now
|
||||
//
|
||||
// it is an error to call Yield() recursively unless the value of
|
||||
// onlyIfNeeded is true
|
||||
//
|
||||
// WARNING: this function is dangerous as it can lead to unexpected
|
||||
// reentrancies (i.e. when called from an event handler it
|
||||
// may result in calling the same event handler again), use
|
||||
// with _extreme_ care or, better, don't use at all!
|
||||
// process all currently pending events right now
|
||||
//
|
||||
// it is an error to call Yield() recursively unless the value of
|
||||
// onlyIfNeeded is true
|
||||
//
|
||||
// WARNING: this function is dangerous as it can lead to unexpected
|
||||
// reentrancies (i.e. when called from an event handler it
|
||||
// may result in calling the same event handler again), use
|
||||
// with _extreme_ care or, better, don't use at all!
|
||||
bool Yield(bool onlyIfNeeded = false);
|
||||
virtual bool YieldFor(long eventsToProcess) = 0;
|
||||
|
||||
// returns true if the main thread is inside a Yield() call
|
||||
// returns true if the main thread is inside a Yield() call
|
||||
virtual bool IsYielding() const
|
||||
{ return m_isInsideYield; }
|
||||
|
||||
// returns true if events of the given event category should be immediately
|
||||
// processed inside a wxApp::Yield() call or rather should be queued for
|
||||
// later processing by the main event loop
|
||||
// returns true if events of the given event category should be immediately
|
||||
// processed inside a wxApp::Yield() call or rather should be queued for
|
||||
// later processing by the main event loop
|
||||
virtual bool IsEventAllowedInsideYield(wxEventCategory cat) const
|
||||
{ return (m_eventsToProcessInsideYield & cat) != 0; }
|
||||
|
||||
@@ -150,6 +414,13 @@ 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)
|
||||
@@ -223,7 +494,7 @@ private:
|
||||
#include "wx/cocoa/evtloop.h"
|
||||
#elif defined(__WXDFB__)
|
||||
#include "wx/dfb/evtloop.h"
|
||||
#elif defined(__WXGTK20__)
|
||||
#elif defined(__WXGTK__)
|
||||
#include "wx/gtk/evtloop.h"
|
||||
#else // other platform
|
||||
|
||||
|
333
include/wx/fswatcher.h
Normal file
333
include/wx/fswatcher.h
Normal file
@@ -0,0 +1,333 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/fswatcher.h
|
||||
// Purpose: wxFileSystemWatcherBase
|
||||
// Author: Bartosz Bekier
|
||||
// Created: 2009-05-23
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 2009 Bartosz Bekier <bartosz.bekier@gmail.com>
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WX_FSWATCHER_BASE_H_
|
||||
#define _WX_FSWATCHER_BASE_H_
|
||||
|
||||
#include "wx/defs.h"
|
||||
|
||||
#if wxUSE_FSWATCHER
|
||||
|
||||
#include "wx/log.h"
|
||||
#include "wx/event.h"
|
||||
#include "wx/evtloop.h"
|
||||
#include "wx/filename.h"
|
||||
#include "wx/dir.h"
|
||||
#include "wx/hashmap.h"
|
||||
|
||||
#define wxTRACE_FSWATCHER "fswatcher"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxFileSystemWatcherEventType & wxFileSystemWatcherEvent
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Possible types of file system events.
|
||||
* This is a subset that will work fine an all platforms (actually, we will
|
||||
* see how it works on Mac).
|
||||
*
|
||||
* We got 2 types of error events:
|
||||
* - warning: these are not fatal and further events can still be generated
|
||||
* - error: indicates fatal error and causes that no more events will happen
|
||||
*/
|
||||
enum
|
||||
{
|
||||
wxFSW_EVENT_CREATE = 0x01,
|
||||
wxFSW_EVENT_DELETE = 0x02,
|
||||
wxFSW_EVENT_RENAME = 0x04,
|
||||
wxFSW_EVENT_MODIFY = 0x08,
|
||||
wxFSW_EVENT_ACCESS = 0x10,
|
||||
|
||||
// error events
|
||||
wxFSW_EVENT_WARNING = 0x20,
|
||||
wxFSW_EVENT_ERROR = 0x40,
|
||||
|
||||
wxFSW_EVENT_ALL = wxFSW_EVENT_CREATE | wxFSW_EVENT_DELETE |
|
||||
wxFSW_EVENT_RENAME | wxFSW_EVENT_MODIFY |
|
||||
wxFSW_EVENT_ACCESS |
|
||||
wxFSW_EVENT_WARNING | wxFSW_EVENT_ERROR
|
||||
};
|
||||
|
||||
/**
|
||||
* Event containing information about file system change.
|
||||
*/
|
||||
class WXDLLIMPEXP_FWD_BASE wxFileSystemWatcherEvent;
|
||||
wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_BASE, wxEVT_FSWATCHER,
|
||||
wxFileSystemWatcherEvent);
|
||||
|
||||
class WXDLLIMPEXP_BASE wxFileSystemWatcherEvent: public wxEvent
|
||||
{
|
||||
public:
|
||||
wxFileSystemWatcherEvent(int changeType, int watchid = wxID_ANY) :
|
||||
wxEvent(watchid, wxEVT_FSWATCHER),
|
||||
m_changeType(changeType)
|
||||
{
|
||||
}
|
||||
|
||||
wxFileSystemWatcherEvent(int changeType, const wxString& errorMsg,
|
||||
int watchid = wxID_ANY) :
|
||||
wxEvent(watchid, wxEVT_FSWATCHER),
|
||||
m_changeType(changeType), m_errorMsg(errorMsg)
|
||||
{
|
||||
}
|
||||
|
||||
wxFileSystemWatcherEvent(int changeType,
|
||||
const wxFileName& path, const wxFileName& newPath,
|
||||
int watchid = wxID_ANY) :
|
||||
wxEvent(watchid, wxEVT_FSWATCHER),
|
||||
m_changeType(changeType), m_path(path), m_newPath(newPath)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path at which the event occurred.
|
||||
*/
|
||||
const wxFileName& GetPath() const
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the path at which the event occurred
|
||||
*/
|
||||
void SetPath(const wxFileName& path)
|
||||
{
|
||||
m_path = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* In case of rename(move?) events, returns the new path related to the
|
||||
* event. The "new" means newer in the sense of time. In case of other
|
||||
* events it returns the same path as GetPath().
|
||||
*/
|
||||
const wxFileName& GetNewPath() const
|
||||
{
|
||||
return m_newPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new path related to the event. See above.
|
||||
*/
|
||||
void SetNewPath(const wxFileName& path)
|
||||
{
|
||||
m_newPath = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of file system event that occurred.
|
||||
*/
|
||||
int GetChangeType() const
|
||||
{
|
||||
return m_changeType;
|
||||
}
|
||||
|
||||
virtual wxEvent* Clone() const
|
||||
{
|
||||
wxFileSystemWatcherEvent* evt = new wxFileSystemWatcherEvent(*this);
|
||||
evt->m_errorMsg = m_errorMsg.Clone();
|
||||
evt->m_path = wxFileName(m_path.GetFullPath().Clone());
|
||||
evt->m_newPath = wxFileName(m_newPath.GetFullPath().Clone());
|
||||
return evt;
|
||||
}
|
||||
|
||||
virtual wxEventCategory GetEventCategory() const
|
||||
{
|
||||
// TODO this has to be merged with "similiar" categories and changed
|
||||
return wxEVT_CATEGORY_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if this error is an error event
|
||||
*/
|
||||
bool IsError() const
|
||||
{
|
||||
return (m_changeType & (wxFSW_EVENT_ERROR | wxFSW_EVENT_WARNING)) != 0;
|
||||
}
|
||||
|
||||
wxString GetErrorDescription() const
|
||||
{
|
||||
return m_errorMsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a wxString describing an event useful for debugging or testing
|
||||
*/
|
||||
wxString ToString() const;
|
||||
|
||||
protected:
|
||||
int m_changeType;
|
||||
wxFileName m_path;
|
||||
wxFileName m_newPath;
|
||||
wxString m_errorMsg;
|
||||
};
|
||||
|
||||
typedef void (wxEvtHandler::*wxFileSystemWatcherEventFunction)
|
||||
(wxFileSystemWatcherEvent&);
|
||||
|
||||
#define wxFileSystemWatcherEventHandler(func) \
|
||||
wxEVENT_HANDLER_CAST(wxFileSystemWatcherEventFunction, func)
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxFileSystemWatcherBase: interface for wxFileSystemWatcher
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Simple container to store information about one watched file
|
||||
*/
|
||||
class wxFSWatchInfo
|
||||
{
|
||||
public:
|
||||
wxFSWatchInfo() :
|
||||
m_path(wxEmptyString), m_events(-1)
|
||||
{
|
||||
}
|
||||
|
||||
wxFSWatchInfo(const wxString& path, int events) :
|
||||
m_path(path), m_events(events)
|
||||
{
|
||||
}
|
||||
|
||||
const wxString& GetPath() const
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
int GetFlags() const
|
||||
{
|
||||
return m_events;
|
||||
}
|
||||
|
||||
protected:
|
||||
wxString m_path;
|
||||
int m_events;
|
||||
};
|
||||
|
||||
WX_DECLARE_STRING_HASH_MAP(wxFSWatchInfo, wxFSWatchInfoMap);
|
||||
|
||||
/**
|
||||
* Encapsulation of platform-specific file system event mechanism
|
||||
*/
|
||||
class wxFSWatcherImpl;
|
||||
|
||||
/**
|
||||
* Main entry point for clients interested in file system events.
|
||||
* Defines interface that can be used to receive that kind of events.
|
||||
*/
|
||||
class WXDLLIMPEXP_BASE wxFileSystemWatcherBase: public wxEvtHandler
|
||||
{
|
||||
public:
|
||||
wxFileSystemWatcherBase();
|
||||
|
||||
virtual ~wxFileSystemWatcherBase();
|
||||
|
||||
/**
|
||||
* Adds path to currently watched files. Any events concerning this
|
||||
* particular path will be sent to handler. Optionally a filter can be
|
||||
* specified to receive only events of particular type.
|
||||
*
|
||||
* Please note that when adding a dir, immediate children will be watched
|
||||
* as well.
|
||||
*/
|
||||
virtual bool Add(const wxFileName& path, int events = wxFSW_EVENT_ALL);
|
||||
|
||||
/**
|
||||
* Like above, but recursively adds every file/dir in the tree rooted in
|
||||
* path. Additionally a file mask can be specified to include only files
|
||||
* of particular type.
|
||||
*/
|
||||
virtual bool AddTree(const wxFileName& path, int events = wxFSW_EVENT_ALL,
|
||||
const wxString& filter = wxEmptyString);
|
||||
|
||||
/**
|
||||
* Removes path from the list of watched paths.
|
||||
*/
|
||||
virtual bool Remove(const wxFileName& path);
|
||||
|
||||
/**
|
||||
* Same as above, but also removes every file belonging to the tree rooted
|
||||
* at path.
|
||||
*/
|
||||
virtual bool RemoveTree(const wxFileName& path);
|
||||
|
||||
/**
|
||||
* Clears the list of currently watched paths.
|
||||
*/
|
||||
virtual bool RemoveAll();
|
||||
|
||||
/**
|
||||
* Returns the number of watched paths
|
||||
*/
|
||||
int GetWatchedPathsCount() const;
|
||||
|
||||
/**
|
||||
* Retrevies all watched paths and places them in wxArrayString. Returns
|
||||
* the number of paths.
|
||||
*
|
||||
* TODO think about API here: we need to return more information (like is
|
||||
* the path watched recursively)
|
||||
*/
|
||||
int GetWatchedPaths(wxArrayString* paths) const;
|
||||
|
||||
wxEvtHandler* GetOwner() const
|
||||
{
|
||||
return m_owner;
|
||||
}
|
||||
|
||||
void SetOwner(wxEvtHandler* handler)
|
||||
{
|
||||
if (!handler)
|
||||
m_owner = this;
|
||||
else
|
||||
m_owner = handler;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
static wxString GetCanonicalPath(const wxFileName& path)
|
||||
{
|
||||
wxFileName path_copy = wxFileName(path);
|
||||
if ( !path_copy.Normalize() )
|
||||
{
|
||||
wxFAIL_MSG(wxString::Format("Unable to normalize path '%s'",
|
||||
path.GetFullPath()));
|
||||
return wxEmptyString;
|
||||
}
|
||||
|
||||
return path_copy.GetFullPath();
|
||||
}
|
||||
|
||||
wxFSWatchInfoMap m_watches; // path=>wxFSWatchInfo map
|
||||
wxFSWatcherImpl* m_service; // file system events service
|
||||
wxEvtHandler* m_owner; // handler for file system events
|
||||
|
||||
friend class wxFSWatcherImpl;
|
||||
};
|
||||
|
||||
// include the platform specific file defining wxFileSystemWatcher
|
||||
// inheriting from wxFileSystemWatcherBase
|
||||
|
||||
#ifdef wxHAS_INOTIFY
|
||||
#include "wx/unix/fswatcher_inotify.h"
|
||||
#define wxFileSystemWatcher wxInotifyFileSystemWatcher
|
||||
#elif defined(wxHAS_KQUEUE)
|
||||
#include "wx/unix/fswatcher_kqueue.h"
|
||||
#define wxFileSystemWatcher wxKqueueFileSystemWatcher
|
||||
#elif defined(__WXMSW__)
|
||||
#include "wx/msw/fswatcher.h"
|
||||
#define wxFileSystemWatcher wxMSWFileSystemWatcher
|
||||
#else
|
||||
#include "wx/generic/fswatcher.h"
|
||||
#define wxFileSystemWatcher wxPollingFileSystemWatcher
|
||||
#endif
|
||||
|
||||
#endif // wxUSE_FSWATCHER
|
||||
|
||||
#endif /* _WX_FSWATCHER_BASE_H_ */
|
26
include/wx/generic/fswatcher.h
Normal file
26
include/wx/generic/fswatcher.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/generic/fswatcher.h
|
||||
// Purpose: wxPollingFileSystemWatcher
|
||||
// Author: Bartosz Bekier
|
||||
// Created: 2009-05-26
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 2009 Bartosz Bekier <bartosz.bekier@gmail.com>
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WX_FSWATCHER_GENERIC_H_
|
||||
#define _WX_FSWATCHER_GENERIC_H_
|
||||
|
||||
#include "wx/defs.h"
|
||||
|
||||
#if wxUSE_FSWATCHER
|
||||
|
||||
class WXDLLIMPEXP_BASE wxPollingFileSystemWatcher : public wxFileSystemWatcherBase
|
||||
{
|
||||
public:
|
||||
|
||||
};
|
||||
|
||||
#endif // wxUSE_FSWATCHER
|
||||
|
||||
#endif /* _WX_FSWATCHER_GENERIC_H_ */
|
@@ -17,9 +17,17 @@
|
||||
|
||||
typedef union _GdkEvent GdkEvent;
|
||||
|
||||
class WXDLLIMPEXP_CORE wxGUIEventLoop : public wxEventLoopBase
|
||||
#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
|
||||
{
|
||||
public:
|
||||
typedef wxUnixEventLoopSource Source;
|
||||
|
||||
wxGUIEventLoop();
|
||||
|
||||
virtual int Run();
|
||||
@@ -33,7 +41,29 @@ public:
|
||||
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
|
||||
|
||||
// the exit code of this event loop
|
||||
int m_exitcode;
|
||||
|
@@ -430,6 +430,13 @@
|
||||
// Recommended setting: 1 (needed by wxSocket)
|
||||
#define wxUSE_STOPWATCH 1
|
||||
|
||||
// Set wxUSE_FSWATCHER to 1 if you want to enable wxFileSystemWatcher
|
||||
//
|
||||
// Default is 1
|
||||
//
|
||||
// Recommended setting: 1
|
||||
#define wxUSE_FSWATCHER 1
|
||||
|
||||
// Setting wxUSE_CONFIG to 1 enables the use of wxConfig and related classes
|
||||
// which allow the application to store its settings in the persistent
|
||||
// storage. Setting this to 1 will also enable on-demand creation of the
|
||||
|
32
include/wx/msw/fswatcher.h
Normal file
32
include/wx/msw/fswatcher.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/msw/fswatcher.h
|
||||
// Purpose: wxMSWFileSystemWatcher
|
||||
// Author: Bartosz Bekier
|
||||
// Created: 2009-05-26
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 2009 Bartosz Bekier <bartosz.bekier@gmail.com>
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WX_FSWATCHER_MSW_H_
|
||||
#define _WX_FSWATCHER_MSW_H_
|
||||
|
||||
#include "wx/defs.h"
|
||||
|
||||
#if wxUSE_FSWATCHER
|
||||
|
||||
class WXDLLIMPEXP_BASE wxMSWFileSystemWatcher : public wxFileSystemWatcherBase
|
||||
{
|
||||
public:
|
||||
wxMSWFileSystemWatcher();
|
||||
|
||||
wxMSWFileSystemWatcher(const wxFileName& path,
|
||||
int events = wxFSW_EVENT_ALL);
|
||||
|
||||
protected:
|
||||
bool Init();
|
||||
};
|
||||
|
||||
#endif // wxUSE_FSWATCHER
|
||||
|
||||
#endif /* _WX_FSWATCHER_MSW_H_ */
|
252
include/wx/msw/private/fswatcher.h
Normal file
252
include/wx/msw/private/fswatcher.h
Normal file
@@ -0,0 +1,252 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/msw/private/fswatcher.h
|
||||
// Purpose: File system watcher impl classes
|
||||
// Author: Bartosz Bekier
|
||||
// Created: 2009-05-26
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 2009 Bartosz Bekier <bartosz.bekier@gmail.com>
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef WX_MSW_PRIVATE_FSWATCHER_H_
|
||||
#define WX_MSW_PRIVATE_FSWATCHER_H_
|
||||
|
||||
#include "wx/filename.h"
|
||||
#include "wx/vector.h"
|
||||
#include "wx/msw/private.h"
|
||||
|
||||
// ============================================================================
|
||||
// wxFSWatcherEntry implementation & helper declarations
|
||||
// ============================================================================
|
||||
|
||||
class wxFSWatcherImplMSW;
|
||||
|
||||
class wxFSWatchEntryMSW : public wxFSWatchInfo
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
BUFFER_SIZE = 4096 // TODO parametrize
|
||||
};
|
||||
|
||||
wxFSWatchEntryMSW(const wxFSWatchInfo& winfo) :
|
||||
wxFSWatchInfo(winfo)
|
||||
{
|
||||
// get handle for this path
|
||||
m_handle = OpenDir(m_path);
|
||||
m_overlapped = (OVERLAPPED*)calloc(1, sizeof(OVERLAPPED));
|
||||
wxZeroMemory(m_buffer);
|
||||
}
|
||||
|
||||
virtual ~wxFSWatchEntryMSW()
|
||||
{
|
||||
wxLogTrace(wxTRACE_FSWATCHER, "Deleting entry '%s'", m_path);
|
||||
|
||||
if (m_handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (!CloseHandle(m_handle))
|
||||
{
|
||||
wxLogSysError(_("Unable to close the handle for '%s'"),
|
||||
m_path);
|
||||
}
|
||||
}
|
||||
delete m_overlapped;
|
||||
}
|
||||
|
||||
bool IsOk() const
|
||||
{
|
||||
return m_handle != INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
HANDLE GetHandle() const
|
||||
{
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
void* GetBuffer()
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
OVERLAPPED* GetOverlapped() const
|
||||
{
|
||||
return m_overlapped;
|
||||
}
|
||||
|
||||
private:
|
||||
// opens dir with all flags, attributes etc. necessary to be later
|
||||
// asynchronous watched with ReadDirectoryChangesW
|
||||
static HANDLE OpenDir(const wxString& path)
|
||||
{
|
||||
HANDLE handle = CreateFile(path, FILE_LIST_DIRECTORY,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE |
|
||||
FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS |
|
||||
FILE_FLAG_OVERLAPPED,
|
||||
NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
wxLogSysError(_("Failed to open directory \"%s\" for monitoring."),
|
||||
path);
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
HANDLE m_handle; // handle to opened directory
|
||||
char m_buffer[BUFFER_SIZE]; // buffer for fs events
|
||||
OVERLAPPED* m_overlapped;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxFSWatchEntryMSW);
|
||||
};
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// wxFSWatcherImplMSW helper classes implementations
|
||||
// ============================================================================
|
||||
|
||||
class wxIOCPService
|
||||
{
|
||||
public:
|
||||
wxIOCPService() :
|
||||
m_iocp(INVALID_HANDLE_VALUE)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
~wxIOCPService()
|
||||
{
|
||||
if (m_iocp != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (!CloseHandle(m_iocp))
|
||||
{
|
||||
wxLogSysError(_("Unable to close I/O completion port handle"));
|
||||
}
|
||||
}
|
||||
m_watches.clear();
|
||||
}
|
||||
|
||||
// associates a wxFSWatchEntryMSW with completion port
|
||||
bool Add(wxSharedPtr<wxFSWatchEntryMSW> watch)
|
||||
{
|
||||
wxCHECK_MSG( m_iocp != INVALID_HANDLE_VALUE, false, "IOCP not init" );
|
||||
wxCHECK_MSG( watch->IsOk(), false, "Invalid watch" );
|
||||
|
||||
// associate with IOCP
|
||||
HANDLE ret = CreateIoCompletionPort(watch->GetHandle(), m_iocp,
|
||||
(ULONG_PTR)watch.get(), 0);
|
||||
if (ret == NULL)
|
||||
{
|
||||
wxLogSysError(_("Unable to associate handle with "
|
||||
"I/O completion port"));
|
||||
return false;
|
||||
}
|
||||
else if (ret != m_iocp)
|
||||
{
|
||||
wxFAIL_MSG(_("Unexpectedly new I/O completion port was created"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// add to watch map
|
||||
wxFSWatchEntries::value_type val(watch->GetPath(), watch);
|
||||
return m_watches.insert(val).second;
|
||||
}
|
||||
|
||||
// post completion packet
|
||||
bool PostEmptyStatus()
|
||||
{
|
||||
wxCHECK_MSG( m_iocp != INVALID_HANDLE_VALUE, false, "IOCP not init" );
|
||||
|
||||
int ret = PostQueuedCompletionStatus(m_iocp, 0, NULL, NULL);
|
||||
if (!ret)
|
||||
{
|
||||
wxLogSysError(_("Unable to post completion status"));
|
||||
}
|
||||
|
||||
return ret != 0;
|
||||
}
|
||||
|
||||
// Wait for completion status to arrive.
|
||||
// This function can block forever in it's wait for completion status.
|
||||
// Use PostEmptyStatus() to wake it up (and end the worker thread)
|
||||
bool GetStatus(unsigned long* count, wxFSWatchEntryMSW** watch,
|
||||
OVERLAPPED** overlapped)
|
||||
{
|
||||
wxCHECK_MSG( m_iocp != INVALID_HANDLE_VALUE, false, "IOCP not init" );
|
||||
wxCHECK_MSG( count != NULL, false, "Null out parameter 'count'");
|
||||
wxCHECK_MSG( watch != NULL, false, "Null out parameter 'watch'");
|
||||
wxCHECK_MSG( overlapped != NULL, false,
|
||||
"Null out parameter 'overlapped'");
|
||||
|
||||
int ret = GetQueuedCompletionStatus(m_iocp, count, (PULONG_PTR)watch,
|
||||
overlapped, INFINITE);
|
||||
if (!ret)
|
||||
{
|
||||
wxLogSysError(_("Unable to dequeue completion packet"));
|
||||
}
|
||||
return ret != 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool Init()
|
||||
{
|
||||
m_iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
|
||||
if (m_iocp == NULL)
|
||||
{
|
||||
wxLogSysError(_("Unable to create I/O completion port"));
|
||||
}
|
||||
return m_iocp != NULL;
|
||||
}
|
||||
|
||||
HANDLE m_iocp;
|
||||
wxFSWatchEntries m_watches;
|
||||
};
|
||||
|
||||
|
||||
class wxIOCPThread : public wxThread
|
||||
{
|
||||
public:
|
||||
wxIOCPThread(wxFSWatcherImplMSW* service, wxIOCPService* iocp);
|
||||
|
||||
// finishes this thread
|
||||
bool Finish();
|
||||
|
||||
protected:
|
||||
// structure to hold information needed to process one native event
|
||||
// this is just a dummy holder, so it doesn't take ownership of it's data
|
||||
struct wxEventProcessingData
|
||||
{
|
||||
wxEventProcessingData(const FILE_NOTIFY_INFORMATION* ne,
|
||||
const wxFSWatchEntryMSW* watch) :
|
||||
nativeEvent(ne), watch(watch)
|
||||
{}
|
||||
|
||||
const FILE_NOTIFY_INFORMATION* nativeEvent;
|
||||
const wxFSWatchEntryMSW* watch;
|
||||
};
|
||||
|
||||
virtual ExitCode Entry();
|
||||
|
||||
// wait for events to occur, read them and send to interested parties
|
||||
// returns false it empty status was read, which means we whould exit
|
||||
// true otherwise
|
||||
bool ReadEvents();
|
||||
|
||||
void ProcessNativeEvents(wxVector<wxEventProcessingData>& events);
|
||||
|
||||
void SendEvent(wxFileSystemWatcherEvent& evt);
|
||||
|
||||
static int Native2WatcherFlags(int flags);
|
||||
|
||||
static wxString FileNotifyInformationToString(
|
||||
const FILE_NOTIFY_INFORMATION& e);
|
||||
|
||||
static wxFileName GetEventPath(const wxFSWatchEntryMSW& watch,
|
||||
const FILE_NOTIFY_INFORMATION& e);
|
||||
|
||||
wxFSWatcherImplMSW* m_service;
|
||||
wxIOCPService* m_iocp;
|
||||
};
|
||||
|
||||
#endif /* WX_MSW_PRIVATE_FSWATCHER_H_ */
|
@@ -430,6 +430,13 @@
|
||||
// Recommended setting: 1 (needed by wxSocket)
|
||||
#define wxUSE_STOPWATCH 1
|
||||
|
||||
// Set wxUSE_FSWATCHER to 1 if you want to enable wxFileSystemWatcher
|
||||
//
|
||||
// Default is 1
|
||||
//
|
||||
// Recommended setting: 1
|
||||
#define wxUSE_FSWATCHER 1
|
||||
|
||||
// Setting wxUSE_CONFIG to 1 enables the use of wxConfig and related classes
|
||||
// which allow the application to store its settings in the persistent
|
||||
// storage. Setting this to 1 will also enable on-demand creation of the
|
||||
|
@@ -430,6 +430,13 @@
|
||||
// Recommended setting: 1 (needed by wxSocket)
|
||||
#define wxUSE_STOPWATCH 1
|
||||
|
||||
// Set wxUSE_FSWATCHER to 1 if you want to enable wxFileSystemWatcher
|
||||
//
|
||||
// Default is 1
|
||||
//
|
||||
// Recommended setting: 1
|
||||
#define wxUSE_FSWATCHER 1
|
||||
|
||||
// Setting wxUSE_CONFIG to 1 enables the use of wxConfig and related classes
|
||||
// which allow the application to store its settings in the persistent
|
||||
// storage. Setting this to 1 will also enable on-demand creation of the
|
||||
|
@@ -430,6 +430,13 @@
|
||||
// Recommended setting: 1 (needed by wxSocket)
|
||||
#define wxUSE_STOPWATCH 1
|
||||
|
||||
// Set wxUSE_FSWATCHER to 1 if you want to enable wxFileSystemWatcher
|
||||
//
|
||||
// Default is 1
|
||||
//
|
||||
// Recommended setting: 1
|
||||
#define wxUSE_FSWATCHER 1
|
||||
|
||||
// Setting wxUSE_CONFIG to 1 enables the use of wxConfig and related classes
|
||||
// which allow the application to store its settings in the persistent
|
||||
// storage. Setting this to 1 will also enable on-demand creation of the
|
||||
|
@@ -11,9 +11,11 @@
|
||||
#ifndef _WX_OSX_COCOA_EVTLOOP_H_
|
||||
#define _WX_OSX_COCOA_EVTLOOP_H_
|
||||
|
||||
class WXDLLIMPEXP_CORE wxGUIEventLoop : public wxEventLoopManual
|
||||
class WXDLLIMPEXP_BASE wxGUIEventLoop : public wxEventLoopManual
|
||||
{
|
||||
public:
|
||||
typedef wxMacEventLoopSource Source;
|
||||
|
||||
wxGUIEventLoop();
|
||||
|
||||
// implement/override base class pure virtual
|
||||
@@ -24,6 +26,31 @@ 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
|
||||
|
||||
private:
|
||||
double m_sleepTime;
|
||||
};
|
||||
|
@@ -431,6 +431,13 @@
|
||||
// Recommended setting: 1 (needed by wxSocket)
|
||||
#define wxUSE_STOPWATCH 1
|
||||
|
||||
// Set wxUSE_FSWATCHER to 1 if you want to enable wxFileSystemWatcher
|
||||
//
|
||||
// Default is 1
|
||||
//
|
||||
// Recommended setting: 1
|
||||
#define wxUSE_FSWATCHER 1
|
||||
|
||||
// Setting wxUSE_CONFIG to 1 enables the use of wxConfig and related classes
|
||||
// which allow the application to store its settings in the persistent
|
||||
// storage. Setting this to 1 will also enable on-demand creation of the
|
||||
|
@@ -430,6 +430,13 @@
|
||||
// Recommended setting: 1 (needed by wxSocket)
|
||||
#define wxUSE_STOPWATCH 1
|
||||
|
||||
// Set wxUSE_FSWATCHER to 1 if you want to enable wxFileSystemWatcher
|
||||
//
|
||||
// Default is 1
|
||||
//
|
||||
// Recommended setting: 1
|
||||
#define wxUSE_FSWATCHER 1
|
||||
|
||||
// Setting wxUSE_CONFIG to 1 enables the use of wxConfig and related classes
|
||||
// which allow the application to store its settings in the persistent
|
||||
// storage. Setting this to 1 will also enable on-demand creation of the
|
||||
|
92
include/wx/private/fswatcher.h
Normal file
92
include/wx/private/fswatcher.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/private/fswatcher.h
|
||||
// Purpose: File system watcher impl classes
|
||||
// Author: Bartosz Bekier
|
||||
// Created: 2009-05-26
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 2009 Bartosz Bekier <bartosz.bekier@gmail.com>
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef WX_PRIVATE_FSWATCHER_H_
|
||||
#define WX_PRIVATE_FSWATCHER_H_
|
||||
|
||||
#include "wx/sharedptr.h"
|
||||
|
||||
#ifdef wxHAS_INOTIFY
|
||||
class wxFSWatchEntryUnix;
|
||||
#define wxFSWatchEntry wxFSWatchEntryUnix
|
||||
WX_DECLARE_STRING_HASH_MAP(wxSharedPtr<wxFSWatchEntry>,wxFSWatchEntries);
|
||||
#include "wx/unix/private/fswatcher_inotify.h"
|
||||
#elif defined(wxHAS_KQUEUE)
|
||||
class wxFSWatchEntryKq;
|
||||
#define wxFSWatchEntry wxFSWatchEntryKq
|
||||
WX_DECLARE_STRING_HASH_MAP(wxSharedPtr<wxFSWatchEntry>,wxFSWatchEntries);
|
||||
#include "wx/unix/private/fswatcher_kqueue.h"
|
||||
#elif defined(__WXMSW__)
|
||||
class wxFSWatchEntryMSW;
|
||||
#define wxFSWatchEntry wxFSWatchEntryMSW
|
||||
WX_DECLARE_STRING_HASH_MAP(wxSharedPtr<wxFSWatchEntry>,wxFSWatchEntries);
|
||||
#include "wx/msw/private/fswatcher.h"
|
||||
#else
|
||||
#define wxFSWatchEntry wxFSWatchEntryPolling
|
||||
#endif
|
||||
|
||||
class wxFSWatcherImpl
|
||||
{
|
||||
public:
|
||||
wxFSWatcherImpl(wxFileSystemWatcherBase* watcher) :
|
||||
m_watcher(watcher)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~wxFSWatcherImpl()
|
||||
{
|
||||
(void) RemoveAll();
|
||||
}
|
||||
|
||||
virtual bool Init() = 0;
|
||||
|
||||
virtual bool Add(const wxFSWatchInfo& winfo)
|
||||
{
|
||||
wxCHECK_MSG( m_watches.find(winfo.GetPath()) == m_watches.end(), false,
|
||||
"Path '%s' is already watched");
|
||||
|
||||
// conctruct watch entry
|
||||
wxSharedPtr<wxFSWatchEntry> watch(new wxFSWatchEntry(winfo));
|
||||
|
||||
if (!DoAdd(watch))
|
||||
return false;
|
||||
|
||||
// add watch to our map (always succeedes, checked above)
|
||||
wxFSWatchEntries::value_type val(watch->GetPath(), watch);
|
||||
return m_watches.insert(val).second;
|
||||
}
|
||||
|
||||
virtual bool Remove(const wxFSWatchInfo& winfo)
|
||||
{
|
||||
wxFSWatchEntries::iterator it = m_watches.find(winfo.GetPath());
|
||||
wxCHECK_MSG( it != m_watches.end(), false, "Path '%s' is not watched");
|
||||
|
||||
wxSharedPtr<wxFSWatchEntry> watch = it->second;
|
||||
m_watches.erase(it);
|
||||
return DoRemove(watch);
|
||||
}
|
||||
|
||||
virtual bool RemoveAll()
|
||||
{
|
||||
m_watches.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool DoAdd(wxSharedPtr<wxFSWatchEntry> watch) = 0;
|
||||
|
||||
virtual bool DoRemove(wxSharedPtr<wxFSWatchEntry> watch) = 0;
|
||||
|
||||
wxFSWatchEntries m_watches;
|
||||
wxFileSystemWatcherBase* m_watcher;
|
||||
};
|
||||
|
||||
|
||||
#endif /* WX_PRIVATE_FSWATCHER_H_ */
|
@@ -426,6 +426,13 @@
|
||||
// Recommended setting: 1 (needed by wxSocket)
|
||||
#define wxUSE_STOPWATCH 1
|
||||
|
||||
// Set wxUSE_FSWATCHER to 1 if you want to enable wxFileSystemWatcher
|
||||
//
|
||||
// Default is 1
|
||||
//
|
||||
// Recommended setting: 1
|
||||
#define wxUSE_FSWATCHER 1
|
||||
|
||||
// Setting wxUSE_CONFIG to 1 enables the use of wxConfig and related classes
|
||||
// which allow the application to store its settings in the persistent
|
||||
// storage. Setting this to 1 will also enable on-demand creation of the
|
||||
|
@@ -429,6 +429,13 @@
|
||||
// Recommended setting: 1 (needed by wxSocket)
|
||||
#define wxUSE_STOPWATCH 1
|
||||
|
||||
// Set wxUSE_FSWATCHER to 1 if you want to enable wxFileSystemWatcher
|
||||
//
|
||||
// Default is 1
|
||||
//
|
||||
// Recommended setting: 1
|
||||
#define wxUSE_FSWATCHER 1
|
||||
|
||||
// Setting wxUSE_CONFIG to 1 enables the use of wxConfig and related classes
|
||||
// which allow the application to store its settings in the persistent
|
||||
// storage. Setting this to 1 will also enable on-demand creation of the
|
||||
|
@@ -1,4 +1,4 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/unix/evtloop.h
|
||||
// Purpose: declares wxEventLoop class
|
||||
// Author: Lukasz Michalski (lm@zork.pl)
|
||||
@@ -27,6 +27,8 @@ 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();
|
||||
@@ -39,7 +41,27 @@ public:
|
||||
virtual bool IsOk() const { return m_dispatcher != NULL; }
|
||||
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
|
||||
|
||||
protected:
|
||||
#if wxUSE_EVENTLOOP_SOURCE
|
||||
// adding/removing sources
|
||||
virtual bool DoAddSource(wxAbstractEventLoopSource* source);
|
||||
virtual bool DoRemoveSource(wxAbstractEventLoopSource* source);
|
||||
#endif
|
||||
|
||||
virtual void OnNextIteration();
|
||||
|
||||
private:
|
||||
|
35
include/wx/unix/fswatcher_inotify.h
Normal file
35
include/wx/unix/fswatcher_inotify.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/unix/fswatcher_inotify.h
|
||||
// Purpose: wxInotifyFileSystemWatcher
|
||||
// Author: Bartosz Bekier
|
||||
// Created: 2009-05-26
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 2009 Bartosz Bekier <bartosz.bekier@gmail.com>
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WX_FSWATCHER_UNIX_H_
|
||||
#define _WX_FSWATCHER_UNIX_H_
|
||||
|
||||
#include "wx/defs.h"
|
||||
|
||||
#if wxUSE_FSWATCHER
|
||||
|
||||
class WXDLLIMPEXP_BASE wxInotifyFileSystemWatcher :
|
||||
public wxFileSystemWatcherBase
|
||||
{
|
||||
public:
|
||||
wxInotifyFileSystemWatcher();
|
||||
|
||||
wxInotifyFileSystemWatcher(const wxFileName& path,
|
||||
int events = wxFSW_EVENT_ALL);
|
||||
|
||||
virtual ~wxInotifyFileSystemWatcher();
|
||||
|
||||
protected:
|
||||
bool Init();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _WX_FSWATCHER_UNIX_H_ */
|
35
include/wx/unix/fswatcher_kqueue.h
Normal file
35
include/wx/unix/fswatcher_kqueue.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/unix/fswatcher_kqueue.h
|
||||
// Purpose: wxKqueueFileSystemWatcher
|
||||
// Author: Bartosz Bekier
|
||||
// Created: 2009-05-26
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 2009 Bartosz Bekier <bartosz.bekier@gmail.com>
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WX_FSWATCHER_KQUEUE_H_
|
||||
#define _WX_FSWATCHER_KQUEUE_H_
|
||||
|
||||
#include "wx/defs.h"
|
||||
|
||||
#if wxUSE_FSWATCHER
|
||||
|
||||
class WXDLLIMPEXP_BASE wxKqueueFileSystemWatcher :
|
||||
public wxFileSystemWatcherBase
|
||||
{
|
||||
public:
|
||||
wxKqueueFileSystemWatcher();
|
||||
|
||||
wxKqueueFileSystemWatcher(const wxFileName& path,
|
||||
int events = wxFSW_EVENT_ALL);
|
||||
|
||||
virtual ~wxKqueueFileSystemWatcher();
|
||||
|
||||
protected:
|
||||
bool Init();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _WX_FSWATCHER_OSX_H_ */
|
71
include/wx/unix/private/fswatcher_inotify.h
Normal file
71
include/wx/unix/private/fswatcher_inotify.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/unix/private/fswatcher_inotify.h
|
||||
// Purpose: File system watcher impl classes
|
||||
// Author: Bartosz Bekier
|
||||
// Created: 2009-05-26
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 2009 Bartosz Bekier <bartosz.bekier@gmail.com>
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef WX_UNIX_PRIVATE_FSWATCHER_INOTIFY_H_
|
||||
#define WX_UNIX_PRIVATE_FSWATCHER_INOTIFY_H_
|
||||
|
||||
#include "wx/filename.h"
|
||||
|
||||
// ============================================================================
|
||||
// wxFSWatcherEntry implementation & helper declarations
|
||||
// ============================================================================
|
||||
|
||||
class wxFSWatcherImplUNIX;
|
||||
|
||||
class wxFSWatchEntry : public wxFSWatchInfo
|
||||
{
|
||||
public:
|
||||
wxFSWatchEntry(const wxFSWatchInfo& winfo) :
|
||||
wxFSWatchInfo(winfo)
|
||||
{
|
||||
}
|
||||
|
||||
int GetWatchDescriptor() const
|
||||
{
|
||||
return m_wd;
|
||||
}
|
||||
|
||||
void SetWatchDescriptor(int wd)
|
||||
{
|
||||
m_wd = wd;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_wd;
|
||||
|
||||
wxDECLARE_NO_COPY_CLASS(wxFSWatchEntry);
|
||||
};
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// wxFSWSourceHandler helper class
|
||||
// ============================================================================
|
||||
|
||||
class wxFSWatcherImplUnix;
|
||||
|
||||
/**
|
||||
* Handler for handling i/o from inotify descriptor
|
||||
*/
|
||||
class wxFSWSourceHandler : public wxEventLoopSourceHandler
|
||||
{
|
||||
public:
|
||||
wxFSWSourceHandler(wxFSWatcherImplUnix* service) :
|
||||
m_service(service)
|
||||
{ }
|
||||
|
||||
virtual void OnReadWaiting();
|
||||
virtual void OnWriteWaiting();
|
||||
virtual void OnExceptionWaiting();
|
||||
|
||||
protected:
|
||||
wxFSWatcherImplUnix* m_service;
|
||||
};
|
||||
|
||||
#endif /* WX_UNIX_PRIVATE_FSWATCHER_INOTIFY_H_ */
|
134
include/wx/unix/private/fswatcher_kqueue.h
Normal file
134
include/wx/unix/private/fswatcher_kqueue.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/unix/private/fswatcher_kqueue.h
|
||||
// Purpose: File system watcher impl classes
|
||||
// Author: Bartosz Bekier
|
||||
// Created: 2009-05-26
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 2009 Bartosz Bekier <bartosz.bekier@gmail.com>
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef WX_UNIX_PRIVATE_FSWATCHER_KQUEUE_H_
|
||||
#define WX_UNIX_PRIVATE_FSWATCHER_KQUEUE_H_
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include "wx/dir.h"
|
||||
#include "wx/debug.h"
|
||||
#include "wx/arrstr.h"
|
||||
|
||||
// ============================================================================
|
||||
// wxFSWatcherEntry implementation & helper declarations
|
||||
// ============================================================================
|
||||
|
||||
class wxFSWatcherImplKqueue;
|
||||
|
||||
class wxFSWatchEntryKq : public wxFSWatchInfo
|
||||
{
|
||||
public:
|
||||
struct wxDirState
|
||||
{
|
||||
wxDirState(const wxFSWatchInfo& winfo)
|
||||
{
|
||||
if (!wxDir::Exists(winfo.GetPath()))
|
||||
return;
|
||||
|
||||
wxDir dir(winfo.GetPath());
|
||||
wxCHECK_RET( dir.IsOpened(),
|
||||
wxString::Format("Unable to open dir '%s'", winfo.GetPath()));
|
||||
|
||||
wxString filename;
|
||||
bool ret = dir.GetFirst(&filename);
|
||||
while (ret)
|
||||
{
|
||||
files.push_back(filename);
|
||||
ret = dir.GetNext(&filename);
|
||||
}
|
||||
}
|
||||
|
||||
wxSortedArrayString files;
|
||||
};
|
||||
|
||||
wxFSWatchEntryKq(const wxFSWatchInfo& winfo) :
|
||||
wxFSWatchInfo(winfo), m_lastState(winfo)
|
||||
{
|
||||
m_fd = wxOpen(m_path, O_RDONLY, 0);
|
||||
if (m_fd == -1)
|
||||
{
|
||||
wxLogSysError(_("Unable to open path '%s'"), m_path);
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~wxFSWatchEntryKq()
|
||||
{
|
||||
(void) Close();
|
||||
}
|
||||
|
||||
bool Close()
|
||||
{
|
||||
if (!IsOk())
|
||||
return false;
|
||||
|
||||
int ret = close(m_fd);
|
||||
if (ret == -1)
|
||||
{
|
||||
wxLogSysError(_("Unable to close path '%s'"), m_path);
|
||||
}
|
||||
m_fd = -1;
|
||||
|
||||
return ret != -1;
|
||||
}
|
||||
|
||||
bool IsOk() const
|
||||
{
|
||||
return m_fd != -1;
|
||||
}
|
||||
|
||||
int GetFileDescriptor() const
|
||||
{
|
||||
return m_fd;
|
||||
}
|
||||
|
||||
void RefreshState()
|
||||
{
|
||||
m_lastState = wxDirState(*this);
|
||||
}
|
||||
|
||||
const wxDirState& GetLastState() const
|
||||
{
|
||||
return m_lastState;
|
||||
}
|
||||
|
||||
private:
|
||||
int m_fd;
|
||||
wxDirState m_lastState;
|
||||
|
||||
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_ */
|
Reference in New Issue
Block a user