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