diff --git a/Build/Notepad3.ini b/Build/Notepad3.ini index 8a339cff8..e663f3f44 100644 --- a/Build/Notepad3.ini +++ b/Build/Notepad3.ini @@ -14,7 +14,7 @@ SettingsVersion=5 ;DenyVirtualSpaceAccess=0 ;filebrowser.exe=minipath.exe ;grepWin.exe=grepWinNP3.exe -;FileCheckInterval=2000 +;FileCheckInterval=2000 (min: 500[msec] - if equal or less, notify immediately) ;FileChangedIndicator=[@] ;FileDeletedIndicator=[X] ;FileDlgFilters= diff --git a/src/Config/Config.cpp b/src/Config/Config.cpp index 14e9a303b..b34ff9591 100644 --- a/src/Config/Config.cpp +++ b/src/Config/Config.cpp @@ -1257,7 +1257,7 @@ void LoadSettings() } bDirtyFlag = true; } - Settings2.FileCheckInterval = clampul(Settings2.FileCheckInterval, 120UL, (24UL*60*60*1000) << 1); // min: 120msec max: 48h + Settings2.FileCheckInterval = clampul(Settings2.FileCheckInterval, MIN_FC_POLL_INTERVAL, (24UL * 60 * 60 * 1000) << 1); // min: 500msec max: 48h FileWatching.FileCheckInterval = Settings2.FileCheckInterval; IniSectionGetString(IniSecSettings2, L"FileChangedIndicator", L"[@]", Settings2.FileChangedIndicator, COUNTOF(Settings2.FileChangedIndicator)); diff --git a/src/Helpers.h b/src/Helpers.h index 80ef4a5e2..9fe86b38a 100644 --- a/src/Helpers.h +++ b/src/Helpers.h @@ -420,11 +420,13 @@ bool IsRunAsAdmin(); void BackgroundWorker_Init(BackgroundWorker* worker, HWND hwnd, const HPATHL hFilePath); void BackgroundWorker_Start(BackgroundWorker* worker, _beginthreadex_proc_type routine, LPVOID property); -void BackgroundWorker_Cancel(BackgroundWorker *worker); -void BackgroundWorker_Destroy(BackgroundWorker *worker); +void BackgroundWorker_Cancel(BackgroundWorker* worker); +void BackgroundWorker_Destroy(BackgroundWorker* worker); +inline bool BackgroundWorker_Continue(BackgroundWorker* worker) { + return (worker) ? (WaitForSingleObject(worker->eventCancel, 0) != WAIT_OBJECT_0) : false; +} inline void BackgroundWorker_End(BackgroundWorker* worker, unsigned int retcode) { if (worker) { _endthreadex(retcode); }} -inline bool BackgroundWorker_Continue(BackgroundWorker* worker) { return (worker) ? (WaitForSingleObject(worker->eventCancel, 0) != WAIT_OBJECT_0) : false; } bool BitmapMergeAlpha(HBITMAP hbmp,COLORREF crDest); diff --git a/src/Notepad3.c b/src/Notepad3.c index 1baa5b231..079345619 100644 --- a/src/Notepad3.c +++ b/src/Notepad3.c @@ -12581,17 +12581,24 @@ unsigned int WINAPI FileChangeObserver(LPVOID lpParam) BackgroundWorker* const worker = &(pFCOBSVData->worker); + assert(!IS_VALID_HANDLE(pFCOBSVData->hFileChanged) && "ChangeHandle not properly closed!"); + + pFCOBSVData->hFileChanged = FindFirstChangeNotificationW(Path_Get(pFCOBSVData->worker.hFilePath), false, + FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | + FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | + FILE_NOTIFY_CHANGE_LAST_WRITE); + while (BackgroundWorker_Continue(worker)) { - switch (WaitForSingleObject(pFCOBSVData->hFileChanged, (FileWatching.FileCheckInterval >> 1))) { + switch (WaitForSingleObject(pFCOBSVData->hFileChanged, 100)) { case WAIT_TIMEOUT: - // okay, wait again until done + // okay, check BGWorker cancellation or wait again until done break; case WAIT_OBJECT_0: - if (/*FileWatching.MonitoringLog*/ false) { - NotifyIfFileHasChanged(false); // immediate notification + if (pFCOBSVData->bNotifyImmediate) { + NotifyIfFileHasChanged(/*(!)*/false); // immediate notification } else { WatchTimerProc(NULL, 0, 0ULL, 0); // rely on FileCheckInterval } @@ -12607,7 +12614,7 @@ unsigned int WINAPI FileChangeObserver(LPVOID lpParam) } } - FindCloseChangeNotification(pFCOBSVData->hFileChanged); + FindCloseChangeNotification(pFCOBSVData->hFileChanged); // stop monitoring pFCOBSVData->hFileChanged = INVALID_HANDLE_VALUE; BackgroundWorker_End(worker, retcode); @@ -12633,6 +12640,8 @@ void InstallFileWatching(const bool bInstall) { bool const bExclusiveLock = (FileWatching.FileWatchingMode == FWM_EXCLUSIVELOCK); bool const bWatchFile = (FileWatching.FileWatchingMode != FWM_DONT_CARE) && !bExclusiveLock; + s_FileChgObsvrData.bNotifyImmediate = (FileWatching.FileCheckInterval <= MIN_FC_POLL_INTERVAL); + // always release exclusive file lock in any case if (IS_VALID_HANDLE(_hCurrFileHandle)) { CloseHandle(_hCurrFileHandle); @@ -12661,12 +12670,7 @@ void InstallFileWatching(const bool bInstall) { // Save data of current file ResetFileObservationData(false); // (!) false - assert(!IS_VALID_HANDLE(s_FileChgObsvrData.hFileChanged) && "ChangeHandle not properly closed!"); - - s_FileChgObsvrData.hFileChanged = FindFirstChangeNotificationW(Path_Get(hdir_pth), false, - FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | - FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | - FILE_NOTIFY_CHANGE_LAST_WRITE); + Path_Reset(s_FileChgObsvrData.worker.hFilePath, Path_Get(hdir_pth)); // directory monitoring BackgroundWorker_Start(&(s_FileChgObsvrData.worker), FileChangeObserver, &s_FileChgObsvrData); } diff --git a/src/TypeDefs.h b/src/TypeDefs.h index 9eb7ab1b5..06b22cba8 100644 --- a/src/TypeDefs.h +++ b/src/TypeDefs.h @@ -852,11 +852,14 @@ typedef struct FCOBSRVDATA_T { HANDLE hEventFileDeleted; HANDLE hFileChanged; // FindFirstChangeNotification() + bool bNotifyImmediate; BackgroundWorker worker; } FCOBSRVDATA_T, *PFCOBSRVDATA_T; -#define INIT_FCOBSRV_T { 0UL, { 0 }, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, { NULL, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, NULL } } +#define INIT_FCOBSRV_T { 0UL, { 0 }, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, false, { NULL, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, NULL } } + +#define MIN_FC_POLL_INTERVAL (500UL) //=============================================================================