diff --git a/Shuttle.entitlements b/Shuttle.entitlements
new file mode 100644
index 0000000..e7f7f62
--- /dev/null
+++ b/Shuttle.entitlements
@@ -0,0 +1,15 @@
+
+
+
+
+ com.apple.security.automation.apple-events
+
+ com.apple.security.temporary-exception.apple-events
+
+ com.apple.Terminal
+ com.googlecode.iterm2
+
+ com.apple.security.get-task-allow
+
+
+
\ No newline at end of file
diff --git a/Shuttle.xcodeproj/project.pbxproj b/Shuttle.xcodeproj/project.pbxproj
index d174fef..3222d0e 100644
--- a/Shuttle.xcodeproj/project.pbxproj
+++ b/Shuttle.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 46;
+ objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@@ -398,9 +398,13 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.8;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
+ ARCHS = "$(ARCHS_STANDARD)";
+ VALID_ARCHS = "arm64 x86_64";
+ SUPPORTS_MACCATALYST = NO;
+ EXCLUDED_ARCHS = "";
};
name = Debug;
};
@@ -409,7 +413,7 @@
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
@@ -431,7 +435,7 @@
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
- GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
@@ -440,8 +444,12 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.8;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
SDKROOT = macosx;
+ ARCHS = "$(ARCHS_STANDARD)";
+ VALID_ARCHS = "arm64 x86_64";
+ SUPPORTS_MACCATALYST = NO;
+ EXCLUDED_ARCHS = "";
};
name = Release;
};
@@ -454,10 +462,12 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Shuttle/Shuttle-Prefix.pch";
INFOPLIST_FILE = "Shuttle/Shuttle-Info.plist";
- MACOSX_DEPLOYMENT_TARGET = 10.9;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
PRODUCT_BUNDLE_IDENTIFIER = "shuttle.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
+ ARCHS = "$(ARCHS_STANDARD)";
+ VALID_ARCHS = "arm64 x86_64";
};
name = Debug;
};
@@ -470,10 +480,12 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Shuttle/Shuttle-Prefix.pch";
INFOPLIST_FILE = "Shuttle/Shuttle-Info.plist";
- MACOSX_DEPLOYMENT_TARGET = 10.9;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
PRODUCT_BUNDLE_IDENTIFIER = "shuttle.${PRODUCT_NAME:rfc1034identifier}";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app;
+ ARCHS = "$(ARCHS_STANDARD)";
+ VALID_ARCHS = "arm64 x86_64";
};
name = Release;
};
diff --git a/Shuttle/AppDelegate.m b/Shuttle/AppDelegate.m
index 2f77935..d71dfee 100644
--- a/Shuttle/AppDelegate.m
+++ b/Shuttle/AppDelegate.m
@@ -6,6 +6,9 @@
#import "AppDelegate.h"
#import "AboutWindowController.h"
+// Add version detection macro for macOS compatibility
+#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[NSProcessInfo processInfo] operatingSystemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
+
@implementation AppDelegate
- (void) awakeFromNib {
@@ -72,19 +75,9 @@ - (void) awakeFromNib {
[statusItem setMenu:menu];
[statusItem setImage: regularIcon];
- // Check for AppKit Version, add support for darkmode if > 10.9
- BOOL oldAppKitVersion = (floor(NSAppKitVersionNumber) <= 1265);
-
- // 10.10 or higher, dont load the alt image let OS X style it.
- if (!oldAppKitVersion)
- {
- regularIcon.template = YES;
- }
- // Load the alt image for OS X < 10.10
- else{
- [statusItem setHighlightMode:YES];
- [statusItem setAlternateImage: altIcon];
- }
+ // Modern macOS versions (10.10+) support dynamic icons
+ // Since we now require 10.15+, we can always use template images
+ regularIcon.template = YES;
launchAtLoginController = [[LaunchAtLoginController alloc] init];
// Needed to trigger the menuWillOpen event
@@ -563,11 +556,12 @@ - (void) openHost:(NSMenuItem *) sender {
else {
passParameters = @[escapedObject, terminalTitle];
}
- // Check if Url
- if (url)
+ // Modern macOS permission prompt: System will automatically prompt on first attempt
+
+ // Check if url is valid
+ if (url && [self isValidURL:escapedObject])
{
[[NSWorkspace sharedWorkspace] openURL:url];
-
}
//If the JSON file is set to use iTerm
else if ( [terminalPref rangeOfString: @"iterm"].location !=NSNotFound ) {
@@ -723,6 +717,38 @@ - (IBAction)showImportPanel:(id)sender {
}
+// New: Simplified permission check - relies on system prompts
+- (BOOL)checkAppleEventsPermission {
+ // In macOS 10.15+, system will automatically prompt permissions, return YES
+ return YES;
+}
+
+// New: Simplified permission request - provide user guidance
+- (void)requestAppleEventsPermission {
+ NSAlert *alert = [[NSAlert alloc] init];
+ [alert setMessageText:@"Permission Required"];
+ [alert setInformativeText:@"Shuttle requires Accessibility permissions to control terminal applications. Please go to System Preferences → Security & Privacy → Accessibility, add and enable Shuttle."];
+ [alert addButtonWithTitle:@"Open System Preferences"];
+ [alert addButtonWithTitle:@"Later"];
+
+ if ([alert runModal] == NSAlertFirstButtonReturn) {
+ [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility"]];
+ }
+}
+
+// New: Enhanced URL validation
+- (BOOL)isValidURL:(NSString *)string {
+ NSURL *url = [NSURL URLWithString:string];
+ if (!url) return NO;
+
+ NSString *scheme = [url scheme];
+ if (!scheme) return NO;
+
+ // Only allow standard protocols
+ NSArray *validSchemes = @[@"http", @"https", @"ftp", @"file", @"ssh", @"telnet"];
+ return [validSchemes containsObject:scheme.lowercaseString];
+}
+
-(void) throwError:(NSString*)errorMessage additionalInfo:(NSString*)errorInfo continueOnErrorOption:(BOOL)continueOption {
NSAlert *alert = [[NSAlert alloc] init];
[alert setInformativeText:errorInfo];
diff --git a/Shuttle/Shuttle-Info.plist b/Shuttle/Shuttle-Info.plist
index b760d03..dda7449 100644
--- a/Shuttle/Shuttle-Info.plist
+++ b/Shuttle/Shuttle-Info.plist
@@ -27,7 +27,9 @@
LSUIElement
NSAppleEventsUsageDescription
- Shuttle needs Automation privileges in Security & Privacy to run applescripts
+ Shuttle needs Automation privileges to control Terminal.app and iTerm2 for SSH connections
+ NSAppleEventsUsageDescriptionAutomation
+ Shuttle uses AppleScript to open SSH connections in your preferred terminal application
NSHumanReadableCopyright
Copyright © 2016 Trevor Fitzgerald. All rights reserved.
NSMainNibFile