]>
Commit | Line | Data |
---|---|---|
489468fe | 1 | ///////////////////////////////////////////////////////////////////////////// |
80fdcdb9 | 2 | // Name: src/osx/core/utilsexc_base.cpp |
489468fe SC |
3 | // Purpose: wxMacLaunch |
4 | // Author: Ryan Norton | |
5 | // Modified by: | |
6 | // Created: 2005-06-21 | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) Ryan Norton | |
9 | // Licence: wxWindows licence | |
10 | // Notes: Source was originally in utilsexc_cf.cpp,1.6 then moved | |
11 | // to totally unrelated hid.cpp,1.8. | |
12 | ///////////////////////////////////////////////////////////////////////////// | |
13 | ||
14 | //=========================================================================== | |
15 | // DECLARATIONS | |
16 | //=========================================================================== | |
17 | ||
18 | //--------------------------------------------------------------------------- | |
19 | // Pre-compiled header stuff | |
20 | //--------------------------------------------------------------------------- | |
21 | ||
22 | // For compilers that support precompilation, includes "wx.h". | |
23 | #include "wx/wxprec.h" | |
24 | ||
25 | // WX includes | |
26 | #ifndef WX_PRECOMP | |
27 | #include "wx/string.h" | |
28 | #include "wx/log.h" | |
29 | #include "wx/intl.h" | |
30 | #include "wx/utils.h" | |
31 | #include "wx/wxcrt.h" | |
32 | #endif // WX_PRECOMP | |
33 | ||
34 | // Mac Includes | |
35 | #include <CoreFoundation/CoreFoundation.h> | |
36 | #ifndef __WXOSX_IPHONE__ | |
37 | #include <ApplicationServices/ApplicationServices.h> | |
38 | #endif | |
39 | ||
40 | // More WX Includes | |
41 | #include "wx/filename.h" | |
c8ef3d55 | 42 | #include "wx/osx/core/cfstring.h" |
b2767951 | 43 | #include "wx/osx/core/private.h" |
489468fe SC |
44 | |
45 | // Default path style | |
46 | #define kDefaultPathStyle kCFURLPOSIXPathStyle | |
47 | ||
5815e959 VZ |
48 | #if wxUSE_SOCKETS |
49 | // global pointer which lives in the base library, set from the net one (see | |
50 | // sockosx.cpp) and used from the GUI code (see utilsexc_cf.cpp) -- ugly but | |
51 | // needed hack, see the above-mentioned files for more information | |
52 | class wxSocketManager; | |
53 | extern WXDLLIMPEXP_BASE wxSocketManager *wxOSXSocketManagerCF; | |
54 | wxSocketManager *wxOSXSocketManagerCF = NULL; | |
55 | #endif // wxUSE_SOCKETS | |
56 | ||
26632ccd | 57 | #if ( !wxUSE_GUI && !wxOSX_USE_IPHONE ) || wxOSX_USE_COCOA_OR_CARBON |
b2767951 KO |
58 | |
59 | // have a fast version for mac code that returns the version as a return value | |
60 | ||
03647350 VZ |
61 | long UMAGetSystemVersion() |
62 | { | |
b2767951 KO |
63 | static SInt32 sUMASystemVersion = 0 ; |
64 | if ( sUMASystemVersion == 0 ) | |
65 | { | |
66 | verify_noerr(Gestalt(gestaltSystemVersion, &sUMASystemVersion)); | |
67 | } | |
03647350 | 68 | return sUMASystemVersion ; |
b2767951 KO |
69 | } |
70 | ||
71 | // our OS version is the same in non GUI and GUI cases | |
72 | wxOperatingSystemId wxGetOsVersion(int *majorVsn, int *minorVsn) | |
73 | { | |
5755acd7 JS |
74 | // This returns 10 and 6 for OS X 10.6, consistent with behaviour on |
75 | // other platforms. | |
76 | SInt32 maj, min; | |
77 | Gestalt(gestaltSystemVersionMajor, &maj); | |
78 | Gestalt(gestaltSystemVersionMinor, &min); | |
79 | ||
80 | if ( majorVsn != NULL ) | |
81 | *majorVsn = maj; | |
82 | ||
83 | if ( minorVsn != NULL ) | |
84 | *minorVsn = min; | |
85 | ||
86 | #if 0 | |
b2767951 KO |
87 | SInt32 theSystem; |
88 | Gestalt(gestaltSystemVersion, &theSystem); | |
89 | ||
90 | if ( majorVsn != NULL ) | |
91 | *majorVsn = (theSystem >> 8); | |
92 | ||
93 | if ( minorVsn != NULL ) | |
94 | *minorVsn = (theSystem & 0xFF); | |
5755acd7 | 95 | #endif |
b2767951 KO |
96 | return wxOS_MAC_OSX_DARWIN; |
97 | } | |
98 | ||
99 | #include <sys/utsname.h> | |
100 | ||
101 | wxString wxGetOsDescription() | |
102 | { | |
103 | struct utsname name; | |
104 | uname(&name); | |
9a83f860 | 105 | return wxString::Format(wxT("Mac OS X (%s %s %s)"), |
b2767951 KO |
106 | wxString::FromAscii(name.sysname).c_str(), |
107 | wxString::FromAscii(name.release).c_str(), | |
108 | wxString::FromAscii(name.machine).c_str()); | |
109 | } | |
110 | ||
489468fe SC |
111 | //=========================================================================== |
112 | // IMPLEMENTATION | |
113 | //=========================================================================== | |
114 | ||
115 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
116 | // | |
117 | // wxMacLaunch | |
118 | // | |
119 | // argv is the command line split up, with the application path first | |
120 | // flags are the flags from wxExecute | |
121 | // process is the process passed from wxExecute for pipe streams etc. | |
122 | // returns -1 on error for wxEXEC_SYNC and 0 on error for wxEXEC_ASYNC | |
123 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
124 | bool wxMacLaunch(char **argv) | |
125 | { | |
126 | // Obtains the number of arguments for determining the size of | |
127 | // the CFArray used to hold them | |
128 | CFIndex cfiCount = 0; | |
129 | for(char** argvcopy = argv; *argvcopy != NULL ; ++argvcopy) | |
130 | { | |
131 | ++cfiCount; | |
132 | } | |
133 | ||
134 | // If there is not a single argument then there is no application | |
135 | // to launch | |
136 | if(cfiCount == 0) | |
137 | { | |
138 | wxLogDebug(wxT("wxMacLaunch No file to launch!")); | |
139 | return false ; | |
140 | } | |
141 | ||
142 | // Path to bundle | |
143 | wxString path = *argv++; | |
144 | ||
145 | // Create a CFURL for the application path | |
146 | // Created this way because we are opening a bundle which is a directory | |
147 | CFURLRef cfurlApp = | |
148 | CFURLCreateWithFileSystemPath( | |
149 | kCFAllocatorDefault, | |
150 | wxCFStringRef(path), | |
151 | kDefaultPathStyle, | |
152 | true); //false == not a directory | |
153 | ||
154 | // Check for error from the CFURL | |
155 | if(!cfurlApp) | |
156 | { | |
157 | wxLogDebug(wxT("wxMacLaunch Can't open path: %s"), path.c_str()); | |
158 | return false ; | |
159 | } | |
160 | ||
161 | // Create a CFBundle from the CFURL created earlier | |
162 | CFBundleRef cfbApp = CFBundleCreate(kCFAllocatorDefault, cfurlApp); | |
163 | ||
164 | // Check to see if CFBundleCreate returned an error, | |
165 | // and if it did this was an invalid bundle or not a bundle | |
166 | // at all (maybe a simple directory etc.) | |
167 | if(!cfbApp) | |
168 | { | |
169 | wxLogDebug(wxT("wxMacLaunch Bad bundle: %s"), path.c_str()); | |
170 | CFRelease(cfurlApp); | |
171 | return false ; | |
172 | } | |
173 | ||
174 | // Get the bundle type and make sure its an 'APPL' bundle | |
175 | // Otherwise we're dealing with something else here... | |
176 | UInt32 dwBundleType, dwBundleCreator; | |
177 | CFBundleGetPackageInfo(cfbApp, &dwBundleType, &dwBundleCreator); | |
178 | if(dwBundleType != 'APPL') | |
179 | { | |
180 | wxLogDebug(wxT("wxMacLaunch Not an APPL bundle: %s"), path.c_str()); | |
181 | CFRelease(cfbApp); | |
182 | CFRelease(cfurlApp); | |
183 | return false ; | |
184 | } | |
185 | ||
186 | // Create a CFArray for dealing with the command line | |
187 | // arguments to the bundle | |
188 | CFMutableArrayRef cfaFiles = CFArrayCreateMutable(kCFAllocatorDefault, | |
189 | cfiCount-1, &kCFTypeArrayCallBacks); | |
190 | if(!cfaFiles) //This should never happen | |
191 | { | |
192 | wxLogDebug(wxT("wxMacLaunch Could not create CFMutableArray")); | |
193 | CFRelease(cfbApp); | |
194 | CFRelease(cfurlApp); | |
195 | return false ; | |
196 | } | |
197 | ||
198 | // Loop through command line arguments to the bundle, | |
199 | // turn them into CFURLs and then put them in cfaFiles | |
200 | // For use to launch services call | |
65391c8f PC |
201 | for( ; *argv != NULL ; ++argv) |
202 | { | |
489468fe SC |
203 | // Check for '<' as this will ring true for |
204 | // CFURLCreateWithString but is generally not considered | |
205 | // typical on mac but is usually passed here from wxExecute | |
206 | if (wxStrcmp(*argv, wxT("<")) == 0) | |
207 | continue; | |
208 | ||
209 | ||
210 | CFURLRef cfurlCurrentFile; // CFURL to hold file path | |
211 | wxFileName argfn(*argv); // Filename for path | |
212 | ||
213 | if(argfn.DirExists()) | |
214 | { | |
215 | // First, try creating as a directory | |
216 | cfurlCurrentFile = CFURLCreateWithFileSystemPath( | |
217 | kCFAllocatorDefault, | |
218 | wxCFStringRef(*argv), | |
219 | kDefaultPathStyle, | |
220 | true); //true == directory | |
221 | } | |
222 | else if(argfn.FileExists()) | |
223 | { | |
224 | // And if it isn't a directory try creating it | |
225 | // as a regular file | |
226 | cfurlCurrentFile = CFURLCreateWithFileSystemPath( | |
227 | kCFAllocatorDefault, | |
228 | wxCFStringRef(*argv), | |
229 | kDefaultPathStyle, | |
230 | false); //false == regular file | |
231 | } | |
232 | else | |
233 | { | |
234 | // Argument did not refer to | |
235 | // an entry in the local filesystem, | |
236 | // so try creating it through CFURLCreateWithString | |
237 | cfurlCurrentFile = CFURLCreateWithString( | |
238 | kCFAllocatorDefault, | |
239 | wxCFStringRef(*argv), | |
240 | NULL); | |
241 | } | |
242 | ||
243 | // Continue in the loop if the CFURL could not be created | |
244 | if(!cfurlCurrentFile) | |
245 | { | |
246 | wxLogDebug( | |
247 | wxT("wxMacLaunch Could not create CFURL for argument:%s"), | |
248 | *argv); | |
249 | continue; | |
250 | } | |
251 | ||
252 | // Add the valid CFURL to the argument array and then | |
253 | // release it as the CFArray adds a ref count to it | |
65391c8f PC |
254 | CFArrayAppendValue( |
255 | cfaFiles, | |
256 | cfurlCurrentFile | |
257 | ); | |
258 | CFRelease(cfurlCurrentFile); // array has retained it | |
259 | } | |
489468fe SC |
260 | |
261 | // Create a LSLaunchURLSpec for use with LSOpenFromURLSpec | |
262 | // Note that there are several flag options (launchFlags) such | |
263 | // as kLSLaunchDontSwitch etc. and maybe we could be more | |
264 | // picky about the flags we choose | |
265 | LSLaunchURLSpec launchspec; | |
266 | launchspec.appURL = cfurlApp; | |
267 | launchspec.itemURLs = cfaFiles; | |
268 | launchspec.passThruParams = NULL; //AEDesc* | |
269 | launchspec.launchFlags = kLSLaunchDefaults; | |
270 | launchspec.asyncRefCon = NULL; | |
271 | ||
272 | // Finally, call LSOpenFromURL spec with our arguments | |
273 | // 2nd parameter is a pointer to a CFURL that gets | |
274 | // the actual path launched by the function | |
275 | OSStatus status = LSOpenFromURLSpec(&launchspec, NULL); | |
276 | ||
277 | // Cleanup corefoundation references | |
278 | CFRelease(cfbApp); | |
279 | CFRelease(cfurlApp); | |
280 | CFRelease(cfaFiles); | |
281 | ||
282 | // Check for error from LSOpenFromURLSpec | |
283 | if(status != noErr) | |
284 | { | |
285 | wxLogDebug(wxT("wxMacLaunch LSOpenFromURLSpec Error: %d"), | |
286 | (int)status); | |
287 | return false ; | |
288 | } | |
289 | ||
290 | // No error from LSOpenFromURLSpec, so app was launched | |
291 | return true ; | |
292 | } | |
293 | ||
7c38b3a5 | 294 | #endif // wxOSX_USE_COCOA_OR_CARBON |