macOS support fixes

* 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
This commit is contained in:
Andrew Spiering
2023-09-19 20:58:12 -07:00
parent 92733d1a69
commit f40657ea04
9 changed files with 268 additions and 46 deletions

View File

@@ -0,0 +1,100 @@
// 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