]> git.saurik.com Git - wxWidgets.git/blob - src/osx/core/utilsexc_base.cpp
implement wxEventLoop::DispatchTimeout() for wxGTK (thanks Paul) and rewrote it to...
[wxWidgets.git] / src / osx / core / utilsexc_base.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: mac/corefoundation/utilsexc_base.cpp
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"
42 #include "wx/osx/core/cfstring.h"
43 #include "wx/osx/core/private.h"
44
45 // Default path style
46 #define kDefaultPathStyle kCFURLPOSIXPathStyle
47
48 extern bool WXDLLEXPORT wxIsDebuggerRunning()
49 {
50 // TODO : try to find out ...
51 return false;
52 }
53
54 #if wxOSX_USE_COCOA_OR_CARBON
55
56 // have a fast version for mac code that returns the version as a return value
57
58 long UMAGetSystemVersion()
59 {
60 static SInt32 sUMASystemVersion = 0 ;
61 if ( sUMASystemVersion == 0 )
62 {
63 verify_noerr(Gestalt(gestaltSystemVersion, &sUMASystemVersion));
64 }
65 return sUMASystemVersion ;
66 }
67
68 // our OS version is the same in non GUI and GUI cases
69 wxOperatingSystemId wxGetOsVersion(int *majorVsn, int *minorVsn)
70 {
71 SInt32 theSystem;
72 Gestalt(gestaltSystemVersion, &theSystem);
73
74 if ( majorVsn != NULL )
75 *majorVsn = (theSystem >> 8);
76
77 if ( minorVsn != NULL )
78 *minorVsn = (theSystem & 0xFF);
79
80 return wxOS_MAC_OSX_DARWIN;
81 }
82
83 #include <sys/utsname.h>
84
85 wxString wxGetOsDescription()
86 {
87 struct utsname name;
88 uname(&name);
89 return wxString::Format(_T("Mac OS X (%s %s %s)"),
90 wxString::FromAscii(name.sysname).c_str(),
91 wxString::FromAscii(name.release).c_str(),
92 wxString::FromAscii(name.machine).c_str());
93 }
94
95 #endif // wxOSX_USE_COCOA_OR_CARBON
96
97 //===========================================================================
98 // IMPLEMENTATION
99 //===========================================================================
100
101 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
102 //
103 // wxMacLaunch
104 //
105 // argv is the command line split up, with the application path first
106 // flags are the flags from wxExecute
107 // process is the process passed from wxExecute for pipe streams etc.
108 // returns -1 on error for wxEXEC_SYNC and 0 on error for wxEXEC_ASYNC
109 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
110 bool wxMacLaunch(char **argv)
111 {
112 // Obtains the number of arguments for determining the size of
113 // the CFArray used to hold them
114 CFIndex cfiCount = 0;
115 for(char** argvcopy = argv; *argvcopy != NULL ; ++argvcopy)
116 {
117 ++cfiCount;
118 }
119
120 // If there is not a single argument then there is no application
121 // to launch
122 if(cfiCount == 0)
123 {
124 wxLogDebug(wxT("wxMacLaunch No file to launch!"));
125 return false ;
126 }
127
128 // Path to bundle
129 wxString path = *argv++;
130
131 // Create a CFURL for the application path
132 // Created this way because we are opening a bundle which is a directory
133 CFURLRef cfurlApp =
134 CFURLCreateWithFileSystemPath(
135 kCFAllocatorDefault,
136 wxCFStringRef(path),
137 kDefaultPathStyle,
138 true); //false == not a directory
139
140 // Check for error from the CFURL
141 if(!cfurlApp)
142 {
143 wxLogDebug(wxT("wxMacLaunch Can't open path: %s"), path.c_str());
144 return false ;
145 }
146
147 // Create a CFBundle from the CFURL created earlier
148 CFBundleRef cfbApp = CFBundleCreate(kCFAllocatorDefault, cfurlApp);
149
150 // Check to see if CFBundleCreate returned an error,
151 // and if it did this was an invalid bundle or not a bundle
152 // at all (maybe a simple directory etc.)
153 if(!cfbApp)
154 {
155 wxLogDebug(wxT("wxMacLaunch Bad bundle: %s"), path.c_str());
156 CFRelease(cfurlApp);
157 return false ;
158 }
159
160 // Get the bundle type and make sure its an 'APPL' bundle
161 // Otherwise we're dealing with something else here...
162 UInt32 dwBundleType, dwBundleCreator;
163 CFBundleGetPackageInfo(cfbApp, &dwBundleType, &dwBundleCreator);
164 if(dwBundleType != 'APPL')
165 {
166 wxLogDebug(wxT("wxMacLaunch Not an APPL bundle: %s"), path.c_str());
167 CFRelease(cfbApp);
168 CFRelease(cfurlApp);
169 return false ;
170 }
171
172 // Create a CFArray for dealing with the command line
173 // arguments to the bundle
174 CFMutableArrayRef cfaFiles = CFArrayCreateMutable(kCFAllocatorDefault,
175 cfiCount-1, &kCFTypeArrayCallBacks);
176 if(!cfaFiles) //This should never happen
177 {
178 wxLogDebug(wxT("wxMacLaunch Could not create CFMutableArray"));
179 CFRelease(cfbApp);
180 CFRelease(cfurlApp);
181 return false ;
182 }
183
184 // Loop through command line arguments to the bundle,
185 // turn them into CFURLs and then put them in cfaFiles
186 // For use to launch services call
187 for( ; *argv != NULL ; ++argv)
188 {
189 // Check for '<' as this will ring true for
190 // CFURLCreateWithString but is generally not considered
191 // typical on mac but is usually passed here from wxExecute
192 if (wxStrcmp(*argv, wxT("<")) == 0)
193 continue;
194
195
196 CFURLRef cfurlCurrentFile; // CFURL to hold file path
197 wxFileName argfn(*argv); // Filename for path
198
199 if(argfn.DirExists())
200 {
201 // First, try creating as a directory
202 cfurlCurrentFile = CFURLCreateWithFileSystemPath(
203 kCFAllocatorDefault,
204 wxCFStringRef(*argv),
205 kDefaultPathStyle,
206 true); //true == directory
207 }
208 else if(argfn.FileExists())
209 {
210 // And if it isn't a directory try creating it
211 // as a regular file
212 cfurlCurrentFile = CFURLCreateWithFileSystemPath(
213 kCFAllocatorDefault,
214 wxCFStringRef(*argv),
215 kDefaultPathStyle,
216 false); //false == regular file
217 }
218 else
219 {
220 // Argument did not refer to
221 // an entry in the local filesystem,
222 // so try creating it through CFURLCreateWithString
223 cfurlCurrentFile = CFURLCreateWithString(
224 kCFAllocatorDefault,
225 wxCFStringRef(*argv),
226 NULL);
227 }
228
229 // Continue in the loop if the CFURL could not be created
230 if(!cfurlCurrentFile)
231 {
232 wxLogDebug(
233 wxT("wxMacLaunch Could not create CFURL for argument:%s"),
234 *argv);
235 continue;
236 }
237
238 // Add the valid CFURL to the argument array and then
239 // release it as the CFArray adds a ref count to it
240 CFArrayAppendValue(
241 cfaFiles,
242 cfurlCurrentFile
243 );
244 CFRelease(cfurlCurrentFile); // array has retained it
245 }
246
247 // Create a LSLaunchURLSpec for use with LSOpenFromURLSpec
248 // Note that there are several flag options (launchFlags) such
249 // as kLSLaunchDontSwitch etc. and maybe we could be more
250 // picky about the flags we choose
251 LSLaunchURLSpec launchspec;
252 launchspec.appURL = cfurlApp;
253 launchspec.itemURLs = cfaFiles;
254 launchspec.passThruParams = NULL; //AEDesc*
255 launchspec.launchFlags = kLSLaunchDefaults;
256 launchspec.asyncRefCon = NULL;
257
258 // Finally, call LSOpenFromURL spec with our arguments
259 // 2nd parameter is a pointer to a CFURL that gets
260 // the actual path launched by the function
261 OSStatus status = LSOpenFromURLSpec(&launchspec, NULL);
262
263 // Cleanup corefoundation references
264 CFRelease(cfbApp);
265 CFRelease(cfurlApp);
266 CFRelease(cfaFiles);
267
268 // Check for error from LSOpenFromURLSpec
269 if(status != noErr)
270 {
271 wxLogDebug(wxT("wxMacLaunch LSOpenFromURLSpec Error: %d"),
272 (int)status);
273 return false ;
274 }
275
276 // No error from LSOpenFromURLSpec, so app was launched
277 return true ;
278 }
279