]> git.saurik.com Git - wxWidgets.git/blob - src/osx/core/utilsexc_base.cpp
should have been part of r74664: Avoid calling gtk_window_get_position() from "config...
[wxWidgets.git] / src / osx / core / utilsexc_base.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/core/utilsexc_base.cpp
3 // Purpose: wxMacLaunch
4 // Author: Ryan Norton
5 // Modified by:
6 // Created: 2005-06-21
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 /////////////////////////////////////////////////////////////////////////////
12
13 //===========================================================================
14 // DECLARATIONS
15 //===========================================================================
16
17 //---------------------------------------------------------------------------
18 // Pre-compiled header stuff
19 //---------------------------------------------------------------------------
20
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
23
24 // WX includes
25 #ifndef WX_PRECOMP
26 #include "wx/string.h"
27 #include "wx/log.h"
28 #include "wx/intl.h"
29 #include "wx/utils.h"
30 #include "wx/wxcrt.h"
31 #endif // WX_PRECOMP
32
33 // Mac Includes
34 #include <CoreFoundation/CoreFoundation.h>
35 #ifndef __WXOSX_IPHONE__
36 #include <ApplicationServices/ApplicationServices.h>
37 #endif
38
39 // More WX Includes
40 #include "wx/filename.h"
41 #include "wx/osx/core/cfstring.h"
42 #include "wx/osx/core/private.h"
43
44 // Default path style
45 #define kDefaultPathStyle kCFURLPOSIXPathStyle
46
47 #if wxUSE_SOCKETS
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
55
56 #if ( !wxUSE_GUI && !wxOSX_USE_IPHONE ) || wxOSX_USE_COCOA_OR_CARBON
57
58 // have a fast version for mac code that returns the version as a return value
59
60 long UMAGetSystemVersion()
61 {
62 static SInt32 sUMASystemVersion = 0 ;
63 if ( sUMASystemVersion == 0 )
64 {
65 verify_noerr(Gestalt(gestaltSystemVersion, &sUMASystemVersion));
66 }
67 return sUMASystemVersion ;
68 }
69
70 // our OS version is the same in non GUI and GUI cases
71 wxOperatingSystemId wxGetOsVersion(int *majorVsn, int *minorVsn)
72 {
73 // This returns 10 and 6 for OS X 10.6, consistent with behaviour on
74 // other platforms.
75 SInt32 maj, min;
76 Gestalt(gestaltSystemVersionMajor, &maj);
77 Gestalt(gestaltSystemVersionMinor, &min);
78
79 if ( majorVsn != NULL )
80 *majorVsn = maj;
81
82 if ( minorVsn != NULL )
83 *minorVsn = min;
84
85 #if 0
86 SInt32 theSystem;
87 Gestalt(gestaltSystemVersion, &theSystem);
88
89 if ( majorVsn != NULL )
90 *majorVsn = (theSystem >> 8);
91
92 if ( minorVsn != NULL )
93 *minorVsn = (theSystem & 0xFF);
94 #endif
95 return wxOS_MAC_OSX_DARWIN;
96 }
97
98 #include <sys/utsname.h>
99
100 wxString wxGetOsDescription()
101 {
102 struct utsname name;
103 uname(&name);
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());
108 }
109
110 //===========================================================================
111 // IMPLEMENTATION
112 //===========================================================================
113
114 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
115 //
116 // wxMacLaunch
117 //
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)
124 {
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)
129 {
130 ++cfiCount;
131 }
132
133 // If there is not a single argument then there is no application
134 // to launch
135 if(cfiCount == 0)
136 {
137 wxLogDebug(wxT("wxMacLaunch No file to launch!"));
138 return false ;
139 }
140
141 // Path to bundle
142 wxString path = *argv++;
143
144 // Create a CFURL for the application path
145 // Created this way because we are opening a bundle which is a directory
146 CFURLRef cfurlApp =
147 CFURLCreateWithFileSystemPath(
148 kCFAllocatorDefault,
149 wxCFStringRef(path),
150 kDefaultPathStyle,
151 true); //false == not a directory
152
153 // Check for error from the CFURL
154 if(!cfurlApp)
155 {
156 wxLogDebug(wxT("wxMacLaunch Can't open path: %s"), path.c_str());
157 return false ;
158 }
159
160 // Create a CFBundle from the CFURL created earlier
161 CFBundleRef cfbApp = CFBundleCreate(kCFAllocatorDefault, cfurlApp);
162
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.)
166 if(!cfbApp)
167 {
168 wxLogDebug(wxT("wxMacLaunch Bad bundle: %s"), path.c_str());
169 CFRelease(cfurlApp);
170 return false ;
171 }
172
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')
178 {
179 wxLogDebug(wxT("wxMacLaunch Not an APPL bundle: %s"), path.c_str());
180 CFRelease(cfbApp);
181 CFRelease(cfurlApp);
182 return false ;
183 }
184
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
190 {
191 wxLogDebug(wxT("wxMacLaunch Could not create CFMutableArray"));
192 CFRelease(cfbApp);
193 CFRelease(cfurlApp);
194 return false ;
195 }
196
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)
201 {
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)
206 continue;
207
208
209 CFURLRef cfurlCurrentFile; // CFURL to hold file path
210 wxFileName argfn(*argv); // Filename for path
211
212 if(argfn.DirExists())
213 {
214 // First, try creating as a directory
215 cfurlCurrentFile = CFURLCreateWithFileSystemPath(
216 kCFAllocatorDefault,
217 wxCFStringRef(*argv),
218 kDefaultPathStyle,
219 true); //true == directory
220 }
221 else if(argfn.FileExists())
222 {
223 // And if it isn't a directory try creating it
224 // as a regular file
225 cfurlCurrentFile = CFURLCreateWithFileSystemPath(
226 kCFAllocatorDefault,
227 wxCFStringRef(*argv),
228 kDefaultPathStyle,
229 false); //false == regular file
230 }
231 else
232 {
233 // Argument did not refer to
234 // an entry in the local filesystem,
235 // so try creating it through CFURLCreateWithString
236 cfurlCurrentFile = CFURLCreateWithString(
237 kCFAllocatorDefault,
238 wxCFStringRef(*argv),
239 NULL);
240 }
241
242 // Continue in the loop if the CFURL could not be created
243 if(!cfurlCurrentFile)
244 {
245 wxLogDebug(
246 wxT("wxMacLaunch Could not create CFURL for argument:%s"),
247 *argv);
248 continue;
249 }
250
251 // Add the valid CFURL to the argument array and then
252 // release it as the CFArray adds a ref count to it
253 CFArrayAppendValue(
254 cfaFiles,
255 cfurlCurrentFile
256 );
257 CFRelease(cfurlCurrentFile); // array has retained it
258 }
259
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;
270
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);
275
276 // Cleanup corefoundation references
277 CFRelease(cfbApp);
278 CFRelease(cfurlApp);
279 CFRelease(cfaFiles);
280
281 // Check for error from LSOpenFromURLSpec
282 if(status != noErr)
283 {
284 wxLogDebug(wxT("wxMacLaunch LSOpenFromURLSpec Error: %d"),
285 (int)status);
286 return false ;
287 }
288
289 // No error from LSOpenFromURLSpec, so app was launched
290 return true ;
291 }
292
293 #endif // wxOSX_USE_COCOA_OR_CARBON