From: Ryan Norton <wxprojects@comcast.net> Date: Thu, 21 Apr 2005 19:58:22 +0000 (+0000) Subject: Add support for launching APPL bundles with wxExecute X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/62705a278a57b8d3dd67222f20b161584a86982d Add support for launching APPL bundles with wxExecute git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@33801 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/docs/changes.txt b/docs/changes.txt index ccc8f9a745..aeaf72176f 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -2,6 +2,13 @@ wxWidgets Change Log - For more verbose changes, see the manual --------------------------------------------------------------- +2.6.1 +----- +All: + +wxMac: +- Added support for launching 'APPL' bundles with wxExecute (usually they have a .app extension and are the ones that reside in the Applications folder). + 2.6.0 ----- diff --git a/src/mac/corefoundation/utilsexc_cf.cpp b/src/mac/corefoundation/utilsexc_cf.cpp index afd5227730..bb6e19d6ed 100644 --- a/src/mac/corefoundation/utilsexc_cf.cpp +++ b/src/mac/corefoundation/utilsexc_cf.cpp @@ -1,11 +1,11 @@ ///////////////////////////////////////////////////////////////////////////// // Name: src/mac/corefoundation/utilsexec_cf.cpp // Purpose: Execution-related utilities for Darwin -// Author: David Elliott +// Author: David Elliott, Ryan Norton (wxMacExecute) // Modified by: Stefan Csomor (added necessary wxT for unicode builds) // Created: 2004-11-04 // RCS-ID: $Id$ -// Copyright: (c) David Elliott +// Copyright: (c) David Elliott, Ryan Norton // Licence: wxWindows licence // Notes: This code comes from src/mac/carbon/utilsexc.cpp,1.11 ///////////////////////////////////////////////////////////////////////////// @@ -19,6 +19,116 @@ #include "wx/stdpaths.h" #include "wx/apptrait.h" +#ifdef __WXCOCOA__ +#include <CoreFoundation/CoreFoundation.h> +#include <ApplicationServices/ApplicationServices.h> +#else +#include "wx/mac/private.h" +#include "LaunchServices.h" +#endif + +#include "wx/uri.h" +#include "wx/mac/corefoundation/cfstring.h" + +long wxMacExecute(wxChar **argv, + int flags, + wxProcess *process) +{ + CFIndex cfiCount = 0; + //get count + for(wxChar** argvcopy = argv; *argvcopy != NULL ; ++argvcopy) + { + ++cfiCount; + } + + if(cfiCount == 0) //no file to launch? + { + wxLogDebug(wxT("wxMacExecute No file to launch!")); + return -1; + } + + CFURLRef cfurlApp = CFURLCreateWithString( + kCFAllocatorDefault, + wxMacCFStringHolder(*argv++, wxLocale::GetSystemEncoding()), + NULL); + wxASSERT(cfurlApp); + + CFBundleRef cfbApp = CFBundleCreate(kCFAllocatorDefault, cfurlApp); + if(!cfbApp) + { + wxLogDebug(wxT("wxMacExecute Bad bundle")); + CFRelease(cfurlApp); + return -1; + } + + + UInt32 dwBundleType, dwBundleCreator; + CFBundleGetPackageInfo(cfbApp, &dwBundleType, &dwBundleCreator); + + //Only call wxMacExecute for .app bundles - others could be actual unix programs + if(dwBundleType != 'APPL') + { + CFRelease(cfurlApp); + return -1; + } + + // + // We have a good bundle - so let's launch it! + // + + CFMutableArrayRef cfaFiles = CFArrayCreateMutable(kCFAllocatorDefault, cfiCount - 1, NULL); + + wxASSERT(cfaFiles); + + if(--cfiCount) + { + for( ; *argv != NULL ; ++argv) + { +// wxLogDebug(*argv); + wxString sCurrentFile; + + if(wxURI(*argv).IsReference()) + sCurrentFile = wxString(wxT("file://")) + *argv; + else + sCurrentFile = *argv; + + CFURLRef cfurlCurrentFile = CFURLCreateWithString( + kCFAllocatorDefault, + wxMacCFStringHolder(sCurrentFile, wxLocale::GetSystemEncoding()), + NULL); + wxASSERT(cfurlCurrentFile); + + CFArrayAppendValue( + cfaFiles, + cfurlCurrentFile + ); + } + } + + LSLaunchURLSpec launchspec; + launchspec.appURL = cfurlApp; + launchspec.itemURLs = cfaFiles; + launchspec.passThruParams = NULL; //AEDesc* + launchspec.launchFlags = kLSLaunchDefaults | kLSLaunchDontSwitch; //TODO: Possibly be smarter with flags + launchspec.asyncRefCon = NULL; + + OSStatus status = LSOpenFromURLSpec(&launchspec, + NULL); //2nd is CFURLRef* really launched + + //cleanup + CFRelease(cfurlApp); + CFRelease(cfaFiles); + + //check for error + if(status != noErr) + { + wxLogDebug(wxString::Format(wxT("wxMacExecute ERROR: %d")), (int)status); + return -1; + } + return 0; //success +} + + #include <CoreFoundation/CFMachPort.h> #include <sys/wait.h> extern "C" { diff --git a/src/unix/utilsunx.cpp b/src/unix/utilsunx.cpp index 8336c2d68b..072a66b54a 100644 --- a/src/unix/utilsunx.cpp +++ b/src/unix/utilsunx.cpp @@ -237,6 +237,12 @@ int wxKill(long pid, wxSignal sig, wxKillError *rc, int flags) #define WXEXECUTE_NARGS 127 +#if defined(__DARWIN__) +long wxMacExecute(wxChar **argv, + int flags, + wxProcess *process); +#endif + long wxExecute( const wxString& command, int flags, wxProcess *process ) { wxCHECK_MSG( !command.empty(), 0, wxT("can't exec empty command") ); @@ -307,8 +313,14 @@ long wxExecute( const wxString& command, int flags, wxProcess *process ) } while(*cptr); argv[argc] = NULL; + long lRc; +#if defined(__DARWIN__) + if( (lRc = wxMacExecute(argv, flags, process)) != -1) + return lRc; +#endif + // do execute the command - long lRc = wxExecute(argv, flags, process); + lRc = wxExecute(argv, flags, process); // clean up argc = 0; @@ -436,7 +448,7 @@ bool wxPipeInputStream::CanRead() const #ifdef __VMS #pragma message disable codeunreachable #endif - + long wxExecute(wxChar **argv, int flags, wxProcess *process) @@ -588,7 +600,7 @@ long wxExecute(wxChar **argv, } execvp (*mb_argv, mb_argv); - + fprintf(stderr, "execvp("); // CS changed ppc to ppc_ as ppc is not available under mac os CW Mach-O for ( char **ppc_ = mb_argv; *ppc_; ppc_++ )