]>
Commit | Line | Data |
---|---|---|
1ccb7433 DE |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: mac/corefoundation/utilsexc_base.cpp | |
05718a98 | 3 | // Purpose: wxMacLaunch |
1ccb7433 DE |
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 | ||
7db33dd7 SC |
14 | //=========================================================================== |
15 | // DECLARATIONS | |
16 | //=========================================================================== | |
17 | ||
18 | //--------------------------------------------------------------------------- | |
19 | // Pre-compiled header stuff | |
20 | //--------------------------------------------------------------------------- | |
21 | ||
1ccb7433 DE |
22 | // For compilers that support precompilation, includes "wx.h". |
23 | #include "wx/wxprec.h" | |
7db33dd7 SC |
24 | |
25 | // WX includes | |
1ccb7433 DE |
26 | #ifndef WX_PRECOMP |
27 | #include "wx/string.h" | |
28 | #include "wx/log.h" | |
29 | #include "wx/intl.h" | |
30 | #include "wx/utils.h" | |
cdfc78b8 | 31 | #include "wx/wxcrt.h" |
1ccb7433 DE |
32 | #endif // WX_PRECOMP |
33 | ||
7db33dd7 | 34 | // Mac Includes |
1ccb7433 DE |
35 | #include <CoreFoundation/CoreFoundation.h> |
36 | #include <ApplicationServices/ApplicationServices.h> | |
37 | ||
7db33dd7 SC |
38 | // More WX Includes |
39 | #include "wx/filename.h" | |
1ccb7433 DE |
40 | #include "wx/mac/corefoundation/cfstring.h" |
41 | ||
7db33dd7 | 42 | // Default path style |
7db33dd7 | 43 | #define kDefaultPathStyle kCFURLPOSIXPathStyle |
7db33dd7 SC |
44 | |
45 | //=========================================================================== | |
46 | // IMPLEMENTATION | |
47 | //=========================================================================== | |
48 | ||
49 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
50 | // | |
05718a98 | 51 | // wxMacLaunch |
7db33dd7 SC |
52 | // |
53 | // argv is the command line split up, with the application path first | |
a8d69700 | 54 | // flags are the flags from wxExecute |
7db33dd7 SC |
55 | // process is the process passed from wxExecute for pipe streams etc. |
56 | // returns -1 on error for wxEXEC_SYNC and 0 on error for wxEXEC_ASYNC | |
57 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
05718a98 | 58 | bool wxMacLaunch(char **argv) |
1ccb7433 | 59 | { |
7db33dd7 SC |
60 | // Obtains the number of arguments for determining the size of |
61 | // the CFArray used to hold them | |
1ccb7433 | 62 | CFIndex cfiCount = 0; |
05718a98 | 63 | for(char** argvcopy = argv; *argvcopy != NULL ; ++argvcopy) |
1ccb7433 DE |
64 | { |
65 | ++cfiCount; | |
66 | } | |
67 | ||
7db33dd7 SC |
68 | // If there is not a single argument then there is no application |
69 | // to launch | |
70 | if(cfiCount == 0) | |
1ccb7433 | 71 | { |
05718a98 VZ |
72 | wxLogDebug(wxT("wxMacLaunch No file to launch!")); |
73 | return false ; | |
1ccb7433 | 74 | } |
a8d69700 | 75 | |
7db33dd7 SC |
76 | // Path to bundle |
77 | wxString path = *argv++; | |
78 | ||
79 | // Create a CFURL for the application path | |
80 | // Created this way because we are opening a bundle which is a directory | |
a8d69700 | 81 | CFURLRef cfurlApp = |
7db33dd7 | 82 | CFURLCreateWithFileSystemPath( |
1ccb7433 | 83 | kCFAllocatorDefault, |
504f8052 | 84 | wxCFStringRef(path), |
a8d69700 | 85 | kDefaultPathStyle, |
7db33dd7 | 86 | true); //false == not a directory |
1ccb7433 | 87 | |
7db33dd7 SC |
88 | // Check for error from the CFURL |
89 | if(!cfurlApp) | |
90 | { | |
05718a98 VZ |
91 | wxLogDebug(wxT("wxMacLaunch Can't open path: %s"), path.c_str()); |
92 | return false ; | |
7db33dd7 SC |
93 | } |
94 | ||
95 | // Create a CFBundle from the CFURL created earlier | |
1ccb7433 | 96 | CFBundleRef cfbApp = CFBundleCreate(kCFAllocatorDefault, cfurlApp); |
7db33dd7 SC |
97 | |
98 | // Check to see if CFBundleCreate returned an error, | |
99 | // and if it did this was an invalid bundle or not a bundle | |
100 | // at all (maybe a simple directory etc.) | |
1ccb7433 DE |
101 | if(!cfbApp) |
102 | { | |
05718a98 | 103 | wxLogDebug(wxT("wxMacLaunch Bad bundle: %s"), path.c_str()); |
1ccb7433 | 104 | CFRelease(cfurlApp); |
05718a98 | 105 | return false ; |
1ccb7433 | 106 | } |
a8d69700 | 107 | |
7db33dd7 SC |
108 | // Get the bundle type and make sure its an 'APPL' bundle |
109 | // Otherwise we're dealing with something else here... | |
1ccb7433 DE |
110 | UInt32 dwBundleType, dwBundleCreator; |
111 | CFBundleGetPackageInfo(cfbApp, &dwBundleType, &dwBundleCreator); | |
1ccb7433 DE |
112 | if(dwBundleType != 'APPL') |
113 | { | |
05718a98 | 114 | wxLogDebug(wxT("wxMacLaunch Not an APPL bundle: %s"), path.c_str()); |
7db33dd7 | 115 | CFRelease(cfbApp); |
1ccb7433 | 116 | CFRelease(cfurlApp); |
05718a98 | 117 | return false ; |
1ccb7433 | 118 | } |
a8d69700 | 119 | |
7db33dd7 SC |
120 | // Create a CFArray for dealing with the command line |
121 | // arguments to the bundle | |
a8d69700 | 122 | CFMutableArrayRef cfaFiles = CFArrayCreateMutable(kCFAllocatorDefault, |
7db33dd7 SC |
123 | cfiCount-1, &kCFTypeArrayCallBacks); |
124 | if(!cfaFiles) //This should never happen | |
1ccb7433 | 125 | { |
05718a98 | 126 | wxLogDebug(wxT("wxMacLaunch Could not create CFMutableArray")); |
7db33dd7 SC |
127 | CFRelease(cfbApp); |
128 | CFRelease(cfurlApp); | |
05718a98 | 129 | return false ; |
7db33dd7 | 130 | } |
a8d69700 | 131 | |
7db33dd7 SC |
132 | // Loop through command line arguments to the bundle, |
133 | // turn them into CFURLs and then put them in cfaFiles | |
134 | // For use to launch services call | |
1ccb7433 DE |
135 | for( ; *argv != NULL ; ++argv) |
136 | { | |
a8d69700 | 137 | // Check for '<' as this will ring true for |
7db33dd7 SC |
138 | // CFURLCreateWithString but is generally not considered |
139 | // typical on mac but is usually passed here from wxExecute | |
140 | if (wxStrcmp(*argv, wxT("<")) == 0) | |
141 | continue; | |
a8d69700 VZ |
142 | |
143 | ||
144 | CFURLRef cfurlCurrentFile; // CFURL to hold file path | |
145 | wxFileName argfn(*argv); // Filename for path | |
146 | ||
7db33dd7 SC |
147 | if(argfn.DirExists()) |
148 | { | |
149 | // First, try creating as a directory | |
150 | cfurlCurrentFile = CFURLCreateWithFileSystemPath( | |
151 | kCFAllocatorDefault, | |
504f8052 | 152 | wxCFStringRef(*argv), |
a8d69700 | 153 | kDefaultPathStyle, |
7db33dd7 SC |
154 | true); //true == directory |
155 | } | |
156 | else if(argfn.FileExists()) | |
157 | { | |
158 | // And if it isn't a directory try creating it | |
159 | // as a regular file | |
160 | cfurlCurrentFile = CFURLCreateWithFileSystemPath( | |
161 | kCFAllocatorDefault, | |
504f8052 | 162 | wxCFStringRef(*argv), |
a8d69700 | 163 | kDefaultPathStyle, |
7db33dd7 | 164 | false); //false == regular file |
a8d69700 | 165 | } |
7db33dd7 SC |
166 | else |
167 | { | |
168 | // Argument did not refer to | |
169 | // an entry in the local filesystem, | |
170 | // so try creating it through CFURLCreateWithString | |
171 | cfurlCurrentFile = CFURLCreateWithString( | |
a8d69700 | 172 | kCFAllocatorDefault, |
504f8052 | 173 | wxCFStringRef(*argv), |
a8d69700 | 174 | NULL); |
7db33dd7 | 175 | } |
a8d69700 | 176 | |
7db33dd7 SC |
177 | // Continue in the loop if the CFURL could not be created |
178 | if(!cfurlCurrentFile) | |
179 | { | |
180 | wxLogDebug( | |
05718a98 | 181 | wxT("wxMacLaunch Could not create CFURL for argument:%s"), |
7db33dd7 SC |
182 | *argv); |
183 | continue; | |
184 | } | |
1ccb7433 | 185 | |
7db33dd7 SC |
186 | // Add the valid CFURL to the argument array and then |
187 | // release it as the CFArray adds a ref count to it | |
1ccb7433 DE |
188 | CFArrayAppendValue( |
189 | cfaFiles, | |
190 | cfurlCurrentFile | |
191 | ); | |
192 | CFRelease(cfurlCurrentFile); // array has retained it | |
193 | } | |
a8d69700 | 194 | |
7db33dd7 SC |
195 | // Create a LSLaunchURLSpec for use with LSOpenFromURLSpec |
196 | // Note that there are several flag options (launchFlags) such | |
197 | // as kLSLaunchDontSwitch etc. and maybe we could be more | |
198 | // picky about the flags we choose | |
1ccb7433 DE |
199 | LSLaunchURLSpec launchspec; |
200 | launchspec.appURL = cfurlApp; | |
201 | launchspec.itemURLs = cfaFiles; | |
a8d69700 VZ |
202 | launchspec.passThruParams = NULL; //AEDesc* |
203 | launchspec.launchFlags = kLSLaunchDefaults; | |
1ccb7433 | 204 | launchspec.asyncRefCon = NULL; |
a8d69700 | 205 | |
7db33dd7 SC |
206 | // Finally, call LSOpenFromURL spec with our arguments |
207 | // 2nd parameter is a pointer to a CFURL that gets | |
208 | // the actual path launched by the function | |
209 | OSStatus status = LSOpenFromURLSpec(&launchspec, NULL); | |
1ccb7433 | 210 | |
7db33dd7 SC |
211 | // Cleanup corefoundation references |
212 | CFRelease(cfbApp); | |
1ccb7433 DE |
213 | CFRelease(cfurlApp); |
214 | CFRelease(cfaFiles); | |
a8d69700 | 215 | |
7db33dd7 | 216 | // Check for error from LSOpenFromURLSpec |
1ccb7433 DE |
217 | if(status != noErr) |
218 | { | |
05718a98 | 219 | wxLogDebug(wxT("wxMacLaunch LSOpenFromURLSpec Error: %d"), |
7db33dd7 | 220 | (int)status); |
05718a98 | 221 | return false ; |
1ccb7433 | 222 | } |
a8d69700 | 223 | |
7db33dd7 | 224 | // No error from LSOpenFromURLSpec, so app was launched |
05718a98 | 225 | return true ; |
1ccb7433 DE |
226 | } |
227 |