* Adding macOS FileSystemWatcher, this should allow files to be monitored and update like the other OSs * Reworked how macOS launches processes to use NSTask which just deals with escaped and unescaped paths better * Made a change to the ScriptsBuilder::RunBuildTool, this was adding the escaped values to the path, in reality it should be up to the underlying OS to make sure things are properly escaped, so removed those as they just end up causing issues. Also instead of appending the args to the fileName we just properly use the Arguments variable on the CreateProcessSettings * No longer use open in order to show files in the finder, we use the proper method selectFile * made a slight cleanup change to the MacPlatform Tick function * Added ToNSString functions just to make that easier * Added a ParseArguments function that will take a string and turn it into an array for NSTask
101 lines
3.4 KiB
C++
101 lines
3.4 KiB
C++
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
|
|
|
|
#if PLATFORM_MAC
|
|
#include "MacFileSystemWatcher.h"
|
|
#include "Engine/Platform/Apple/AppleUtils.h"
|
|
#include "Engine/Platform/CriticalSection.h"
|
|
#include "Engine/Platform/Thread.h"
|
|
#include "Engine/Threading/ThreadSpawner.h"
|
|
#include "Engine/Core/Collections/Array.h"
|
|
#include "Engine/Core/Types/StringView.h"
|
|
|
|
void DirectoryWatchCallback( ConstFSEventStreamRef StreamRef, void* FileWatcherPtr, size_t EventCount, void* EventPaths, const FSEventStreamEventFlags EventFlags[], const FSEventStreamEventId EventIDs[] )
|
|
{
|
|
MacFileSystemWatcher* macFileSystemWatcher = (MacFileSystemWatcher*)FileWatcherPtr;
|
|
if (macFileSystemWatcher)
|
|
{
|
|
CFArrayRef EventPathArray = (CFArrayRef)EventPaths;
|
|
for( size_t EventIndex = 0; EventIndex < EventCount; ++EventIndex )
|
|
{
|
|
const FSEventStreamEventFlags Flags = EventFlags[EventIndex];
|
|
if( !(Flags & kFSEventStreamEventFlagItemIsFile) && !(Flags & kFSEventStreamEventFlagItemIsDir) )
|
|
{
|
|
// events about symlinks don't concern us
|
|
continue;
|
|
}
|
|
|
|
auto action = FileSystemAction::Unknown;
|
|
|
|
const bool added = ( Flags & kFSEventStreamEventFlagItemCreated );
|
|
const bool renamed = ( Flags & kFSEventStreamEventFlagItemRenamed );
|
|
const bool modified = ( Flags & kFSEventStreamEventFlagItemModified );
|
|
const bool removed = ( Flags & kFSEventStreamEventFlagItemRemoved );
|
|
|
|
if (added)
|
|
{
|
|
action = FileSystemAction::Create;
|
|
}
|
|
|
|
if (renamed || modified)
|
|
{
|
|
action = FileSystemAction::Delete;
|
|
}
|
|
|
|
if (removed)
|
|
{
|
|
action = FileSystemAction::Modify;
|
|
}
|
|
|
|
const String resolvedPath = AppleUtils::ToString((CFStringRef)CFArrayGetValueAtIndex(EventPathArray,EventIndex));
|
|
|
|
macFileSystemWatcher->OnEvent(resolvedPath, action);
|
|
}
|
|
}
|
|
}
|
|
|
|
MacFileSystemWatcher::MacFileSystemWatcher(const String& directory, bool withSubDirs)
|
|
: FileSystemWatcherBase(directory, withSubDirs)
|
|
{
|
|
|
|
CFStringRef FullPathMac = AppleUtils::ToString(StringView(directory));
|
|
CFArrayRef PathsToWatch = CFArrayCreate(NULL, (const void**)&FullPathMac, 1, NULL);
|
|
|
|
CFAbsoluteTime Latency = 0.2;
|
|
|
|
FSEventStreamContext Context;
|
|
Context.version = 0;
|
|
Context.info = this;
|
|
Context.retain = NULL;
|
|
Context.release = NULL;
|
|
Context.copyDescription = NULL;
|
|
|
|
EventStream = FSEventStreamCreate( NULL,
|
|
&DirectoryWatchCallback,
|
|
&Context,
|
|
PathsToWatch,
|
|
kFSEventStreamEventIdSinceNow,
|
|
Latency,
|
|
kFSEventStreamCreateFlagUseCFTypes | kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents
|
|
);
|
|
|
|
CFRelease(PathsToWatch);
|
|
CFRelease(FullPathMac);
|
|
|
|
FSEventStreamScheduleWithRunLoop( EventStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode );
|
|
FSEventStreamStart( EventStream );
|
|
|
|
IsRunning = true;
|
|
}
|
|
|
|
MacFileSystemWatcher::~MacFileSystemWatcher()
|
|
{
|
|
if (IsRunning)
|
|
{
|
|
FSEventStreamStop(EventStream);
|
|
FSEventStreamUnscheduleFromRunLoop(EventStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
|
FSEventStreamInvalidate(EventStream);
|
|
FSEventStreamRelease(EventStream);
|
|
}
|
|
}
|
|
#endif
|