diff --git a/src/osx/cocoa/utils_base.mm b/src/osx/cocoa/utils_base.mm index ccac04e320..06723c5578 100644 --- a/src/osx/cocoa/utils_base.mm +++ b/src/osx/cocoa/utils_base.mm @@ -18,7 +18,7 @@ #include "wx/app.h" #include "wx/datetime.h" #endif - +#include "wx/filename.h" #include "wx/apptrait.h" #include "wx/osx/private.h" @@ -191,3 +191,95 @@ bool wxDateTime::GetFirstWeekDay(wxDateTime::WeekDay *firstDay) return true; } #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; +} diff --git a/src/unix/utilsunx.cpp b/src/unix/utilsunx.cpp index b4f84fb2e8..4c286d2d1d 100644 --- a/src/unix/utilsunx.cpp +++ b/src/unix/utilsunx.cpp @@ -462,7 +462,7 @@ private: // ---------------------------------------------------------------------------- #if defined(__DARWIN__) && !defined(__WXOSX_IPHONE__) -bool wxMacLaunch(const char* const* argv); +bool wxCocoaLaunch(const char* const* argv, pid_t &pid); #endif 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(), wxT("wxExecute() can be called only from the main thread") ); #endif // wxUSE_THREADS - + pid_t pid; #if defined(__DARWIN__) && !defined(__WXOSX_IPHONE__) + pid = -1; // wxMacLaunch() only executes app bundles and only does it asynchronously. // It returns false if the target is not an app bundle, thus falling // 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 - return -1; + return pid; } #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 // cross our fingers that it works. #ifdef __VMS - pid_t pid = vfork(); + pid = vfork(); #else - pid_t pid = fork(); + pid = fork(); #endif if ( pid == -1 ) // error? {