1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/osx/core/utilsexc_base.cpp 
   3 // Purpose:     wxMacLaunch 
   7 // Copyright:   (c) Ryan Norton 
   8 // Licence:     wxWindows licence 
   9 // Notes:       Source was originally in utilsexc_cf.cpp,1.6 then moved 
  10 //              to totally unrelated hid.cpp,1.8. 
  11 ///////////////////////////////////////////////////////////////////////////// 
  13 //=========================================================================== 
  15 //=========================================================================== 
  17 //--------------------------------------------------------------------------- 
  18 // Pre-compiled header stuff 
  19 //--------------------------------------------------------------------------- 
  21 // For compilers that support precompilation, includes "wx.h". 
  22 #include "wx/wxprec.h" 
  26     #include "wx/string.h" 
  34 #include <CoreFoundation/CoreFoundation.h> 
  35 #ifndef __WXOSX_IPHONE__ 
  36 #include <ApplicationServices/ApplicationServices.h> 
  40 #include "wx/filename.h" 
  41 #include "wx/osx/core/cfstring.h" 
  42 #include "wx/osx/core/private.h" 
  45 #define kDefaultPathStyle kCFURLPOSIXPathStyle 
  48 // global pointer which lives in the base library, set from the net one (see 
  49 // sockosx.cpp) and used from the GUI code (see utilsexc_cf.cpp) -- ugly but 
  50 // needed hack, see the above-mentioned files for more information 
  51 class wxSocketManager
; 
  52 extern WXDLLIMPEXP_BASE wxSocketManager 
*wxOSXSocketManagerCF
; 
  53 wxSocketManager 
*wxOSXSocketManagerCF 
= NULL
; 
  54 #endif // wxUSE_SOCKETS 
  56 #if ( !wxUSE_GUI && !wxOSX_USE_IPHONE ) || wxOSX_USE_COCOA_OR_CARBON 
  58 // have a fast version for mac code that returns the version as a return value 
  60 long UMAGetSystemVersion() 
  62     static SInt32 sUMASystemVersion 
= 0 ; 
  63     if ( sUMASystemVersion 
== 0 ) 
  65         verify_noerr(Gestalt(gestaltSystemVersion
, &sUMASystemVersion
)); 
  67     return sUMASystemVersion 
; 
  70 // our OS version is the same in non GUI and GUI cases 
  71 wxOperatingSystemId 
wxGetOsVersion(int *majorVsn
, int *minorVsn
) 
  73     // This returns 10 and 6 for OS X 10.6, consistent with behaviour on 
  76     Gestalt(gestaltSystemVersionMajor
, &maj
); 
  77     Gestalt(gestaltSystemVersionMinor
, &min
); 
  79     if ( majorVsn 
!= NULL 
) 
  82     if ( minorVsn 
!= NULL 
) 
  87     Gestalt(gestaltSystemVersion
, &theSystem
); 
  89     if ( majorVsn 
!= NULL 
) 
  90         *majorVsn 
= (theSystem 
>> 8); 
  92     if ( minorVsn 
!= NULL 
) 
  93         *minorVsn 
= (theSystem 
& 0xFF); 
  95     return wxOS_MAC_OSX_DARWIN
; 
  98 #include <sys/utsname.h> 
 100 wxString 
wxGetOsDescription() 
 104     return wxString::Format(wxT("Mac OS X (%s %s %s)"), 
 105             wxString::FromAscii(name
.sysname
).c_str(), 
 106             wxString::FromAscii(name
.release
).c_str(), 
 107             wxString::FromAscii(name
.machine
).c_str()); 
 110 //=========================================================================== 
 112 //=========================================================================== 
 114 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
 118 // argv is the command line split up, with the application path first 
 119 // flags are the flags from wxExecute 
 120 // process is the process passed from wxExecute for pipe streams etc. 
 121 // returns -1 on error for wxEXEC_SYNC and 0 on error for wxEXEC_ASYNC 
 122 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
 123 bool wxMacLaunch(char **argv
) 
 125     // Obtains the number of arguments for determining the size of 
 126     // the CFArray used to hold them 
 127     CFIndex cfiCount 
= 0; 
 128     for(char** argvcopy 
= argv
; *argvcopy 
!= NULL 
; ++argvcopy
) 
 133     // If there is not a single argument then there is no application 
 137         wxLogDebug(wxT("wxMacLaunch No file to launch!")); 
 142     wxString path 
= *argv
++; 
 144     // Create a CFURL for the application path 
 145     // Created this way because we are opening a bundle which is a directory 
 147         CFURLCreateWithFileSystemPath( 
 151             true); //false == not a directory 
 153     // Check for error from the CFURL 
 156         wxLogDebug(wxT("wxMacLaunch Can't open path: %s"), path
.c_str()); 
 160     // Create a CFBundle from the CFURL created earlier 
 161     CFBundleRef cfbApp 
= CFBundleCreate(kCFAllocatorDefault
, cfurlApp
); 
 163     // Check to see if CFBundleCreate returned an error, 
 164     // and if it did this was an invalid bundle or not a bundle 
 165     // at all (maybe a simple directory etc.) 
 168         wxLogDebug(wxT("wxMacLaunch Bad bundle: %s"), path
.c_str()); 
 173     // Get the bundle type and make sure its an 'APPL' bundle 
 174     // Otherwise we're dealing with something else here... 
 175     UInt32 dwBundleType
, dwBundleCreator
; 
 176     CFBundleGetPackageInfo(cfbApp
, &dwBundleType
, &dwBundleCreator
); 
 177     if(dwBundleType 
!= 'APPL') 
 179         wxLogDebug(wxT("wxMacLaunch Not an APPL bundle: %s"), path
.c_str()); 
 185     // Create a CFArray for dealing with the command line 
 186     // arguments to the bundle 
 187     CFMutableArrayRef cfaFiles 
= CFArrayCreateMutable(kCFAllocatorDefault
, 
 188                                     cfiCount
-1, &kCFTypeArrayCallBacks
); 
 189     if(!cfaFiles
) //This should never happen 
 191         wxLogDebug(wxT("wxMacLaunch Could not create CFMutableArray")); 
 197     // Loop through command line arguments to the bundle, 
 198     // turn them into CFURLs and then put them in cfaFiles 
 199     // For use to launch services call 
 200     for( ; *argv 
!= NULL 
; ++argv
) 
 202         // Check for '<' as this will ring true for 
 203         // CFURLCreateWithString but is generally not considered 
 204         // typical on mac but is usually passed here from wxExecute 
 205         if (wxStrcmp(*argv
, wxT("<")) == 0) 
 209         CFURLRef cfurlCurrentFile
;    // CFURL to hold file path 
 210         wxFileName 
argfn(*argv
);     // Filename for path 
 212         if(argfn
.DirExists()) 
 214             // First, try creating as a directory 
 215             cfurlCurrentFile 
= CFURLCreateWithFileSystemPath( 
 217                                 wxCFStringRef(*argv
), 
 219                                 true); //true == directory 
 221         else if(argfn
.FileExists()) 
 223             // And if it isn't a directory try creating it 
 225             cfurlCurrentFile 
= CFURLCreateWithFileSystemPath( 
 227                                 wxCFStringRef(*argv
), 
 229                                 false); //false == regular file 
 233             // Argument did not refer to 
 234             // an entry in the local filesystem, 
 235             // so try creating it through CFURLCreateWithString 
 236             cfurlCurrentFile 
= CFURLCreateWithString( 
 238                                 wxCFStringRef(*argv
), 
 242         // Continue in the loop if the CFURL could not be created 
 243         if(!cfurlCurrentFile
) 
 246                 wxT("wxMacLaunch Could not create CFURL for argument:%s"), 
 251         // Add the valid CFURL to the argument array and then 
 252         // release it as the CFArray adds a ref count to it 
 257         CFRelease(cfurlCurrentFile
); // array has retained it 
 260     // Create a LSLaunchURLSpec for use with LSOpenFromURLSpec 
 261     // Note that there are several flag options (launchFlags) such 
 262     // as kLSLaunchDontSwitch etc. and maybe we could be more 
 263     // picky about the flags we choose 
 264     LSLaunchURLSpec launchspec
; 
 265     launchspec
.appURL 
= cfurlApp
; 
 266     launchspec
.itemURLs 
= cfaFiles
; 
 267     launchspec
.passThruParams 
= NULL
; //AEDesc* 
 268     launchspec
.launchFlags 
= kLSLaunchDefaults
; 
 269     launchspec
.asyncRefCon 
= NULL
; 
 271     // Finally, call LSOpenFromURL spec with our arguments 
 272     // 2nd parameter is a pointer to a CFURL that gets 
 273     // the actual path launched by the function 
 274     OSStatus status 
= LSOpenFromURLSpec(&launchspec
, NULL
); 
 276     // Cleanup corefoundation references 
 281     // Check for error from LSOpenFromURLSpec 
 284         wxLogDebug(wxT("wxMacLaunch LSOpenFromURLSpec Error: %d"), 
 289     // No error from LSOpenFromURLSpec, so app was launched 
 293 #endif // wxOSX_USE_COCOA_OR_CARBON