diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index e6eeaaf1a..086e86f7d 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -518,7 +518,7 @@ Thumbnail::Thumbnail () : Thumbnail::~Thumbnail () { - delete thumbImg; + delete thumbImg; thumbImg=NULL; delete [] aeHistogram; delete [] embProfileData; if (embProfile) diff --git a/rtgui/dirbrowser.cc b/rtgui/dirbrowser.cc index 804ddf21b..6b24dbdbf 100644 --- a/rtgui/dirbrowser.cc +++ b/rtgui/dirbrowser.cc @@ -140,6 +140,8 @@ void DirBrowser::updateVolumes () { int nvolumes = GetLogicalDrives (); if (nvolumes!=volumes) { + gdk_threads_enter(); + for (int i=0; i<32; i++) if (((volumes >> i) & 1) && !((nvolumes >> i) & 1)) { // volume i has been deleted for (Gtk::TreeModel::iterator iter = dirTreeModel->children().begin(); iter!=dirTreeModel->children().end(); iter++) @@ -151,14 +153,14 @@ void DirBrowser::updateVolumes () { else if (!((volumes >> i) & 1) && ((nvolumes >> i) & 1)) addRoot ('A'+i); // volume i has been added volumes = nvolumes; + + gdk_threads_leave(); } } int _updateVolumes (void* br) { - gdk_threads_enter (); ((DirBrowser*)br)->updateVolumes (); - gdk_threads_leave (); return 1; } int _updateDirTree (void* br) { diff --git a/rtgui/filebrowser.cc b/rtgui/filebrowser.cc index 2b949c522..022d57f97 100644 --- a/rtgui/filebrowser.cc +++ b/rtgui/filebrowser.cc @@ -190,7 +190,7 @@ struct addparams { FileBrowserEntry* entry; }; -int addfl (void* data) { +int AddEntryUIThread (void* data) { addparams* ap = (addparams*) data; FileBrowserIdleHelper* fbih = ap->fbih; @@ -222,7 +222,7 @@ void FileBrowser::addEntry (FileBrowserEntry* entry) { addparams* ap = new addparams; ap->fbih = fbih; ap->entry = entry; - g_idle_add (addfl, ap); + g_idle_add (AddEntryUIThread, ap); } void FileBrowser::addEntry_ (FileBrowserEntry* entry) { diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc index 874eabf62..e27cc217a 100644 --- a/rtgui/filecatalog.cc +++ b/rtgui/filecatalog.cc @@ -36,19 +36,6 @@ extern Glib::ustring argv0; -#ifdef _WIN32 -int _directoryUpdater (void* cat) { - - ((FileCatalog*)cat)->checkCounter++; - if (((FileCatalog*)cat)->checkCounter==2) { - gdk_threads_enter (); - ((FileCatalog*)cat)->reparseDirectory (); - gdk_threads_leave (); - } - return 1; -} -#endif - FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : selectedDirectoryId(1), listener(NULL), @@ -235,8 +222,6 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : selectedDirectory = ""; #ifdef _WIN32 wdMonitor = NULL; - checkCounter = 2; - g_timeout_add (CHECKTIME, _directoryUpdater, this); #endif } @@ -958,9 +943,16 @@ int FileCatalog::reparseDirectory () { } #ifdef _WIN32 -void FileCatalog::winDirChanged () { +int winDirChangedUITread (void* cat) { + gdk_threads_enter (); + ((FileCatalog*)cat)->reparseDirectory (); + gdk_threads_leave (); - checkCounter = 0; + return 0; +} + +void FileCatalog::winDirChanged () { + g_idle_add(winDirChangedUITread, this); } #endif diff --git a/rtgui/filecatalog.h b/rtgui/filecatalog.h index b72c51860..9420d49d7 100644 --- a/rtgui/filecatalog.h +++ b/rtgui/filecatalog.h @@ -115,7 +115,6 @@ class FileCatalog : public Gtk::VBox, #ifdef _WIN32 WinDirMonitor* wdMonitor; public: - int checkCounter; void winDirChanged (); private: #endif diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index 5f6598ba7..af685339e 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -140,6 +140,7 @@ bool Thumbnail::isSupported () { } const ProcParams& Thumbnail::getProcParams () { + Glib::Mutex::Lock lock(mutex); if (pparamsValid) return pparams; @@ -160,6 +161,7 @@ const ProcParams& Thumbnail::getProcParams () { } void Thumbnail::loadProcParams () { + Glib::Mutex::Lock lock(mutex); pparamsValid = false; if (options.paramsLoadLocation==PLL_Input) { @@ -181,6 +183,7 @@ void Thumbnail::loadProcParams () { } void Thumbnail::clearProcParams (int whoClearedIt) { + Glib::Mutex::Lock lock(mutex); cfs.recentlySaved = false; pparamsValid = false; @@ -208,6 +211,7 @@ bool Thumbnail::hasProcParams () { } void Thumbnail::setProcParams (const ProcParams& pp, int whoChangedIt, bool updateCacheNow) { + Glib::Mutex::Lock lock(mutex); if (pparams!=pp) cfs.recentlySaved = false; @@ -514,6 +518,7 @@ void Thumbnail::updateCache () { } Thumbnail::~Thumbnail () { + Glib::Mutex::Lock lock(mutex); delete [] lastImg; delete tpp; diff --git a/rtgui/windirmonitor.cc b/rtgui/windirmonitor.cc index 732607ea7..d7269da1a 100644 --- a/rtgui/windirmonitor.cc +++ b/rtgui/windirmonitor.cc @@ -19,17 +19,19 @@ #include static void CALLBACK current_directory_monitor_callback (DWORD error, DWORD nBytes, LPOVERLAPPED lpOverlapped) { - -// printf ("hivas: %d %d %d\n", error, nBytes, lpOverlapped); - WinDirMonitor::MonitorData* monData = (WinDirMonitor::MonitorData*)lpOverlapped; if (!nBytes) { delete monData; return; } - if (monData->listener) + // ReadDirectoryChangesW sometimes emits multiple events per change (one for each change type) + // To make sure it's not flooding update, this gets filtered. + time_t curTime= ::time(NULL); + if (monData->listener && ::difftime(curTime, monData->lastTimeUpdateDir)>1.0) { monData->listener->winDirChanged (); + monData->lastTimeUpdateDir = curTime; + } ReadDirectoryChangesW (monData->hDirectory, monData->file_notify_buffer, @@ -37,16 +39,14 @@ static void CALLBACK current_directory_monitor_callback (DWORD error, DWORD nByt FALSE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | - FILE_NOTIFY_CHANGE_ATTRIBUTES | - FILE_NOTIFY_CHANGE_SIZE, + FILE_NOTIFY_CHANGE_LAST_WRITE, &monData->buffer_filled_bytes, &monData->overlapped, current_directory_monitor_callback); } WinDirMonitor::WinDirMonitor (Glib::ustring dirName, WinDirChangeListener* listener) : monData(NULL) { - - wchar_t* wdirname = (wchar_t*)g_utf8_to_utf16 (dirName.raw().c_str(), -1, NULL, NULL, NULL); + wchar_t* wdirname = (wchar_t*)g_utf8_to_utf16 (dirName.c_str(), -1, NULL, NULL, NULL); HANDLE hDirectory = CreateFileW (wdirname, FILE_LIST_DIRECTORY,FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL); g_free (wdirname); @@ -57,6 +57,7 @@ WinDirMonitor::WinDirMonitor (Glib::ustring dirName, WinDirChangeListener* liste monData->buffer_allocated_bytes = 32768; monData->file_notify_buffer = new char [monData->buffer_allocated_bytes]; monData->hDirectory = hDirectory; + monData->lastTimeUpdateDir = ::time(NULL); // printf ("mondata=%d\n", monData); ReadDirectoryChangesW (monData->hDirectory, @@ -65,8 +66,7 @@ WinDirMonitor::WinDirMonitor (Glib::ustring dirName, WinDirChangeListener* liste FALSE, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | - FILE_NOTIFY_CHANGE_ATTRIBUTES | - FILE_NOTIFY_CHANGE_SIZE, + FILE_NOTIFY_CHANGE_LAST_WRITE, &monData->buffer_filled_bytes, &monData->overlapped, current_directory_monitor_callback); diff --git a/rtgui/windirmonitor.h b/rtgui/windirmonitor.h index b0d6243a0..b4f03a4cb 100644 --- a/rtgui/windirmonitor.h +++ b/rtgui/windirmonitor.h @@ -39,6 +39,7 @@ class WinDirMonitor : public Glib::Object { HANDLE hDirectory; WinDirChangeListener* listener; int bigyo; + time_t lastTimeUpdateDir; // for filtering multiple updates events }; private: