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