[OSX] Allow executing the bundle to return pid (#1561)

* Allow bundle execution to return actual pid under OSX

* Remove commented out leftover code

* Remove 'extern' declaration testing remnant
This commit is contained in:
oneeyeman1 2019-10-07 07:14:57 -05:00 committed by Stefan Csomor
parent c92f9e0a17
commit 5b6af7002c
2 changed files with 100 additions and 7 deletions

View File

@ -18,7 +18,7 @@
#include "wx/app.h" #include "wx/app.h"
#include "wx/datetime.h" #include "wx/datetime.h"
#endif #endif
#include "wx/filename.h"
#include "wx/apptrait.h" #include "wx/apptrait.h"
#include "wx/osx/private.h" #include "wx/osx/private.h"
@ -191,3 +191,95 @@ bool wxDateTime::GetFirstWeekDay(wxDateTime::WeekDay *firstDay)
return true; return true;
} }
#endif // wxUSE_DATETIME #endif // wxUSE_DATETIME
bool wxCocoaLaunch(const char* const* argv, pid_t &pid)
{
// Obtains the number of arguments for determining the size of
// the CFArray used to hold them
NSUInteger cfiCount = 0;
for (const char* const* argvcopy = argv; *argvcopy != NULL; ++argvcopy)
{
++cfiCount;
}
// If there is not a single argument then there is no application
// to launch
if(cfiCount == 0)
{
wxLogDebug(wxT("wxCocoaLaunch No file to launch!"));
return false ;
}
// Path to bundle
wxString path = *argv++;
NSError *error = nil;
NSURL *url = [NSURL fileURLWithPath:wxCFStringRef(path).AsNSString() isDirectory:YES];
// Check the URL validity
if( url == nil )
{
wxLogDebug(wxT("wxCocoaLaunch Can't open path: %s"), path.c_str());
return false ;
}
// Loop through command line arguments to the bundle,
// turn them into CFURLs and then put them in cfaFiles
// For use to launch services call
NSMutableArray *params = [[NSMutableArray alloc] init];
for( ; *argv != NULL; ++argv )
{
// Check for '<' as this will ring true for
// CFURLCreateWithString but is generally not considered
// typical on mac but is usually passed here from wxExecute
if (wxStrcmp(*argv, wxT("<")) == 0)
continue;
NSURL *cfurlCurrentFile;
wxFileName argfn(*argv); // Filename for path
wxString dir( *argv );
if(argfn.DirExists())
{
// First, try creating as a directory
cfurlCurrentFile = [NSURL fileURLWithPath:wxCFStringRef(dir).AsNSString() isDirectory:YES];
}
else if(argfn.FileExists())
{
// And if it isn't a directory try creating it
// as a regular file
cfurlCurrentFile = [NSURL fileURLWithPath:wxCFStringRef(dir).AsNSString() isDirectory:NO];
}
else
{
// Argument did not refer to
// an entry in the local filesystem,
// so try creating it through CFURLCreateWithString
cfurlCurrentFile = [NSURL URLWithString:wxCFStringRef(dir).AsNSString()];
}
// Continue in the loop if the CFURL could not be created
if(cfurlCurrentFile == nil)
{
wxLogDebug(
wxT("wxCocoaLaunch Could not create NSURL for argument:%s"),
*argv);
continue;
}
// Add the valid CFURL to the argument array and then
// release it as the CFArray adds a ref count to it
[params addObject:cfurlCurrentFile];
}
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
NSRunningApplication *app = [ws launchApplicationAtURL:url options:NSWorkspaceLaunchAsync
configuration:[NSDictionary dictionaryWithObject:params forKey:NSWorkspaceLaunchConfigurationArguments]
error:&error];
if( app != nil )
pid = [app processIdentifier];
else
{
wxString errorDesc = wxCFStringRef::AsString([error localizedDescription]);
wxLogDebug( wxString::Format( "wxCocoaLaunch failure: error is %s", errorDesc ) );
return false;
}
return true;
}

View File

@ -462,7 +462,7 @@ private:
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#if defined(__DARWIN__) && !defined(__WXOSX_IPHONE__) #if defined(__DARWIN__) && !defined(__WXOSX_IPHONE__)
bool wxMacLaunch(const char* const* argv); bool wxCocoaLaunch(const char* const* argv, pid_t &pid);
#endif #endif
long wxExecute(const wxString& command, int flags, wxProcess *process, long wxExecute(const wxString& command, int flags, wxProcess *process,
@ -585,15 +585,16 @@ long wxExecute(const char* const* argv, int flags, wxProcess* process,
wxASSERT_MSG( wxThread::IsMain(), wxASSERT_MSG( wxThread::IsMain(),
wxT("wxExecute() can be called only from the main thread") ); wxT("wxExecute() can be called only from the main thread") );
#endif // wxUSE_THREADS #endif // wxUSE_THREADS
pid_t pid;
#if defined(__DARWIN__) && !defined(__WXOSX_IPHONE__) #if defined(__DARWIN__) && !defined(__WXOSX_IPHONE__)
pid = -1;
// wxMacLaunch() only executes app bundles and only does it asynchronously. // wxMacLaunch() only executes app bundles and only does it asynchronously.
// It returns false if the target is not an app bundle, thus falling // It returns false if the target is not an app bundle, thus falling
// through to the regular code for non app bundles. // through to the regular code for non app bundles.
if ( !(flags & wxEXEC_SYNC) && wxMacLaunch(argv) ) if ( !(flags & wxEXEC_SYNC) && wxCocoaLaunch(argv, pid) )
{ {
// we don't have any PID to return so just make up something non null // we don't have any PID to return so just make up something non null
return -1; return pid;
} }
#endif // __DARWIN__ #endif // __DARWIN__
@ -641,9 +642,9 @@ long wxExecute(const char* const* argv, int flags, wxProcess* process,
// But on OpenVMS we do not have fork so we have to use vfork and // But on OpenVMS we do not have fork so we have to use vfork and
// cross our fingers that it works. // cross our fingers that it works.
#ifdef __VMS #ifdef __VMS
pid_t pid = vfork(); pid = vfork();
#else #else
pid_t pid = fork(); pid = fork();
#endif #endif
if ( pid == -1 ) // error? if ( pid == -1 ) // error?
{ {