mirror of
https://github.com/atom/atom.git
synced 2026-01-23 13:58:08 -05:00
This still allows atom to open its own source when run from Xcode but will now use the current working directory when launched from the command line with no path argument. Closes #139
264 lines
8.1 KiB
Plaintext
264 lines
8.1 KiB
Plaintext
#import "include/cef_application_mac.h"
|
|
#import "native/atom_cef_client.h"
|
|
#import "native/atom_application.h"
|
|
#import "native/atom_window_controller.h"
|
|
#import "native/atom_cef_app.h"
|
|
#import <getopt.h>
|
|
|
|
@implementation AtomApplication
|
|
|
|
@synthesize arguments=_arguments;
|
|
|
|
+ (AtomApplication *)sharedApplication {
|
|
return (AtomApplication *)[super sharedApplication];
|
|
}
|
|
|
|
+ (id)applicationWithArguments:(char **)argv count:(int)argc {
|
|
AtomApplication *application = [self sharedApplication];
|
|
CefInitialize(CefMainArgs(argc, argv), [self createCefSettings], new AtomCefApp);
|
|
application.arguments = [self parseArguments:argv count:argc];
|
|
|
|
return application;
|
|
}
|
|
|
|
+ (NSDictionary *)parseArguments:(char **)argv count:(int)argc {
|
|
NSMutableDictionary *arguments = [[NSMutableDictionary alloc] init];
|
|
|
|
#ifdef RESOURCE_PATH
|
|
[arguments setObject:[NSString stringWithUTF8String:RESOURCE_PATH] forKey:@"resource-path"];
|
|
#endif
|
|
|
|
// Remove non-posix (i.e. -long_argument_with_one_leading_hyphen) added by OS X from the command line
|
|
int cleanArgc = argc;
|
|
size_t argvSize = argc * sizeof(char *);
|
|
char **cleanArgv = (char **)alloca(argvSize);
|
|
for (int i=0; i < argc; i++) {
|
|
if (strcmp(argv[i], "-NSDocumentRevisionsDebugMode") == 0) { // Xcode inserts useless command-line args by default: http://trac.wxwidgets.org/ticket/13732
|
|
cleanArgc -= 2;
|
|
i++;
|
|
}
|
|
else if (strncmp(argv[i], "-psn_", 5) == 0) { // OS X inserts a -psn_[PID] argument.
|
|
cleanArgc -= 1;
|
|
}
|
|
else {
|
|
cleanArgv[i] = argv[i];
|
|
}
|
|
}
|
|
|
|
int opt;
|
|
int longindex;
|
|
|
|
static struct option longopts[] = {
|
|
{ "executed-from", required_argument, NULL, 'K' },
|
|
{ "resource-path", required_argument, NULL, 'R' },
|
|
{ "benchmark", no_argument, NULL, 'B' },
|
|
{ "test", no_argument, NULL, 'T' },
|
|
{ "stable", no_argument, NULL, 'S' },
|
|
{ "pid", required_argument, NULL, 'P' },
|
|
{ "wait", no_argument, NULL, 'W' },
|
|
{ NULL, 0, NULL, 0 }
|
|
};
|
|
|
|
while ((opt = getopt_long(cleanArgc, cleanArgv, "K:R:BYSP:Wh?", longopts, &longindex)) != -1) {
|
|
NSString *key, *value;
|
|
switch (opt) {
|
|
case 'K':
|
|
case 'R':
|
|
case 'B':
|
|
case 'T':
|
|
case 'S':
|
|
case 'W':
|
|
case 'P':
|
|
key = [NSString stringWithUTF8String:longopts[longindex].name];
|
|
value = optarg ? [NSString stringWithUTF8String:optarg] : @"YES";
|
|
[arguments setObject:value forKey:key];
|
|
break;
|
|
case 0:
|
|
break;
|
|
default:
|
|
NSLog(@"usage: atom [--resource-path=<path>] [<path>]");
|
|
}
|
|
}
|
|
|
|
cleanArgc -= optind;
|
|
cleanArgv += optind;
|
|
|
|
if (cleanArgc > 0) {
|
|
NSString *path = [NSString stringWithUTF8String:cleanArgv[0]];
|
|
path = [self standardizePathToOpen:path withArguments:arguments];
|
|
[arguments setObject:path forKey:@"path"];
|
|
} else {
|
|
NSString *executedFromPath = [arguments objectForKey:@"executed-from"];
|
|
if (executedFromPath) {
|
|
[arguments setObject:executedFromPath forKey:@"path"];
|
|
}
|
|
}
|
|
|
|
return arguments;
|
|
}
|
|
|
|
+ (NSString *)standardizePathToOpen:(NSString *)path withArguments:(NSDictionary *)arguments {
|
|
NSString *standardizedPath = path;
|
|
NSString *executedFromPath = [arguments objectForKey:@"executed-from"];
|
|
if (![standardizedPath isAbsolutePath] && executedFromPath) {
|
|
standardizedPath = [executedFromPath stringByAppendingPathComponent:standardizedPath];
|
|
}
|
|
standardizedPath = [standardizedPath stringByStandardizingPath];
|
|
return standardizedPath;
|
|
}
|
|
|
|
+ (NSString *)supportDirectory {
|
|
NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) objectAtIndex:0];
|
|
NSString *executableName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleExecutable"];
|
|
NSString *supportDirectory = [cachePath stringByAppendingPathComponent:executableName];
|
|
|
|
NSFileManager *fs = [NSFileManager defaultManager];
|
|
NSError *error;
|
|
BOOL success = [fs createDirectoryAtPath:supportDirectory withIntermediateDirectories:YES attributes:nil error:&error];
|
|
if (!success) {
|
|
NSLog(@"Warning: Can't create support directory '%@' because %@", supportDirectory, [error localizedDescription]);
|
|
supportDirectory = @"";
|
|
}
|
|
|
|
return supportDirectory;
|
|
}
|
|
|
|
+ (CefSettings)createCefSettings {
|
|
CefSettings settings;
|
|
|
|
CefString(&settings.cache_path) = [[self supportDirectory] UTF8String];
|
|
CefString(&settings.user_agent) = "";
|
|
CefString(&settings.log_file) = "";
|
|
CefString(&settings.javascript_flags) = "";
|
|
settings.remote_debugging_port = 9090;
|
|
settings.log_severity = LOGSEVERITY_ERROR;
|
|
return settings;
|
|
}
|
|
|
|
- (void)dealloc {
|
|
[_backgroundWindowController release];
|
|
[_arguments release];
|
|
[super dealloc];
|
|
}
|
|
|
|
- (void)open:(NSString *)path pidToKillWhenWindowCloses:(NSNumber *)pid {
|
|
for (NSWindow *window in [self windows]) {
|
|
if (![window isExcludedFromWindowsMenu]) {
|
|
AtomWindowController *controller = [window windowController];
|
|
if ([path isEqualToString:controller.pathToOpen]) {
|
|
[window makeKeyAndOrderFront:nil];
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
AtomWindowController *windowController = [[AtomWindowController alloc] initWithPath:path];
|
|
[windowController setPidToKillOnClose:pid];
|
|
return windowController;
|
|
}
|
|
|
|
- (void)open:(NSString *)path {
|
|
[self open:path pidToKillWhenWindowCloses:nil];
|
|
}
|
|
|
|
- (void)openUnstable:(NSString *)path {
|
|
[[AtomWindowController alloc] initUnstableWithPath:path];
|
|
}
|
|
|
|
- (IBAction)runSpecs:(id)sender {
|
|
[self runSpecsThenExit:NO];
|
|
}
|
|
|
|
- (void)runSpecsThenExit:(BOOL)exitWhenDone {
|
|
[[AtomWindowController alloc] initSpecsThenExit:exitWhenDone];
|
|
}
|
|
|
|
- (IBAction)runBenchmarks:(id)sender {
|
|
[self runBenchmarksThenExit:NO];
|
|
}
|
|
|
|
- (void)runBenchmarksThenExit:(BOOL)exitWhenDone {
|
|
[[AtomWindowController alloc] initBenchmarksThenExit:exitWhenDone];
|
|
}
|
|
|
|
# pragma mark NSApplicationDelegate
|
|
|
|
- (BOOL)shouldOpenFiles {
|
|
if ([self.arguments objectForKey:@"benchmark"]) {
|
|
return NO;
|
|
}
|
|
if ([self.arguments objectForKey:@"test"]) {
|
|
return NO;
|
|
}
|
|
return YES;
|
|
}
|
|
|
|
- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames {
|
|
if ([self shouldOpenFiles]) {
|
|
for (NSString *path in filenames) {
|
|
path = [[self class] standardizePathToOpen:path withArguments:self.arguments];
|
|
NSNumber *pid = [self.arguments objectForKey:@"wait"] ? [self.arguments objectForKey:@"pid"] : nil;
|
|
[self open:path pidToKillWhenWindowCloses:pid];
|
|
}
|
|
if ([filenames count] > 0) {
|
|
_filesOpened = YES;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
|
|
if (!_filesOpened && [self shouldOpenFiles]) {
|
|
NSString *path = [self.arguments objectForKey:@"path"];
|
|
|
|
// Just a hack to open the Atom src by default when we run from xcode
|
|
#ifdef RESOURCE_PATH
|
|
if (!path) path = [NSString stringWithUTF8String:RESOURCE_PATH];
|
|
#endif
|
|
|
|
NSNumber *pid = [self.arguments objectForKey:@"wait"] ? [self.arguments objectForKey:@"pid"] : nil;
|
|
[self open:path pidToKillWhenWindowCloses:pid];
|
|
}
|
|
}
|
|
|
|
- (void)applicationWillFinishLaunching:(NSNotification *)notification {
|
|
_backgroundWindowController = [[AtomWindowController alloc] initInBackground];
|
|
if ([self.arguments objectForKey:@"benchmark"]) {
|
|
[self runBenchmarksThenExit:true];
|
|
}
|
|
else if ([self.arguments objectForKey:@"test"]) {
|
|
[self runSpecsThenExit:true];
|
|
}
|
|
}
|
|
|
|
- (void)applicationWillTerminate:(NSNotification *)notification {
|
|
for (NSWindow *window in [self windows]) {
|
|
[window performClose:self];
|
|
}
|
|
CefShutdown();
|
|
}
|
|
|
|
# pragma mark CefAppProtocol
|
|
|
|
- (BOOL)isHandlingSendEvent {
|
|
return handlingSendEvent_;
|
|
}
|
|
|
|
- (void)setHandlingSendEvent:(BOOL)handlingSendEvent {
|
|
handlingSendEvent_ = handlingSendEvent;
|
|
}
|
|
|
|
- (void)sendEvent:(NSEvent*)event {
|
|
CefScopedSendingEvent sendingEventScoper;
|
|
if ([[self mainMenu] performKeyEquivalent:event]) return;
|
|
|
|
if (_backgroundWindowController && ![self keyWindow] && [event type] == NSKeyDown) {
|
|
[_backgroundWindowController.window makeKeyWindow];
|
|
[_backgroundWindowController.window sendEvent:event];
|
|
}
|
|
else {
|
|
[super sendEvent:event];
|
|
}
|
|
}
|
|
|
|
@end
|