From f137d51cb21cfdc8f2a39bc5047e7b4819885354 Mon Sep 17 00:00:00 2001 From: Charlie Qiu Date: Thu, 12 Jan 2017 23:44:29 +0800 Subject: [PATCH] Use a new approach to implement launch at login. --- .../LaunchHelper.xcodeproj/project.pbxproj | 295 ++++++++ LaunchHelper/LaunchHelper/AppDelegate.swift | 48 ++ .../AppIcon.appiconset/Contents.json | 58 ++ .../LaunchHelper/Base.lproj/MainMenu.xib | 679 ++++++++++++++++++ LaunchHelper/LaunchHelper/Info.plist | 34 + ShadowsocksX-NG.xcodeproj/project.pbxproj | 49 ++ ShadowsocksX-NG/LaunchAtLoginController.h | 2 - ShadowsocksX-NG/LaunchAtLoginController.m | 81 +-- 8 files changed, 1178 insertions(+), 68 deletions(-) create mode 100644 LaunchHelper/LaunchHelper.xcodeproj/project.pbxproj create mode 100644 LaunchHelper/LaunchHelper/AppDelegate.swift create mode 100644 LaunchHelper/LaunchHelper/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 LaunchHelper/LaunchHelper/Base.lproj/MainMenu.xib create mode 100644 LaunchHelper/LaunchHelper/Info.plist diff --git a/LaunchHelper/LaunchHelper.xcodeproj/project.pbxproj b/LaunchHelper/LaunchHelper.xcodeproj/project.pbxproj new file mode 100644 index 0000000..898023d --- /dev/null +++ b/LaunchHelper/LaunchHelper.xcodeproj/project.pbxproj @@ -0,0 +1,295 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 9B6BF93F1E27B1F10061B9A7 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B6BF93E1E27B1F10061B9A7 /* AppDelegate.swift */; }; + 9B6BF9411E27B1F10061B9A7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9B6BF9401E27B1F10061B9A7 /* Assets.xcassets */; }; + 9B6BF9441E27B1F10061B9A7 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9B6BF9421E27B1F10061B9A7 /* MainMenu.xib */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 9B6BF93B1E27B1F10061B9A7 /* LaunchHelper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LaunchHelper.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 9B6BF93E1E27B1F10061B9A7 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 9B6BF9401E27B1F10061B9A7 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 9B6BF9431E27B1F10061B9A7 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 9B6BF9451E27B1F10061B9A7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 9B6BF9381E27B1F10061B9A7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9B6BF9321E27B1F10061B9A7 = { + isa = PBXGroup; + children = ( + 9B6BF93D1E27B1F10061B9A7 /* LaunchHelper */, + 9B6BF93C1E27B1F10061B9A7 /* Products */, + ); + sourceTree = ""; + }; + 9B6BF93C1E27B1F10061B9A7 /* Products */ = { + isa = PBXGroup; + children = ( + 9B6BF93B1E27B1F10061B9A7 /* LaunchHelper.app */, + ); + name = Products; + sourceTree = ""; + }; + 9B6BF93D1E27B1F10061B9A7 /* LaunchHelper */ = { + isa = PBXGroup; + children = ( + 9B6BF93E1E27B1F10061B9A7 /* AppDelegate.swift */, + 9B6BF9401E27B1F10061B9A7 /* Assets.xcassets */, + 9B6BF9421E27B1F10061B9A7 /* MainMenu.xib */, + 9B6BF9451E27B1F10061B9A7 /* Info.plist */, + ); + path = LaunchHelper; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 9B6BF93A1E27B1F10061B9A7 /* LaunchHelper */ = { + isa = PBXNativeTarget; + buildConfigurationList = 9B6BF9481E27B1F10061B9A7 /* Build configuration list for PBXNativeTarget "LaunchHelper" */; + buildPhases = ( + 9B6BF9371E27B1F10061B9A7 /* Sources */, + 9B6BF9381E27B1F10061B9A7 /* Frameworks */, + 9B6BF9391E27B1F10061B9A7 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = LaunchHelper; + productName = LaunchHelper; + productReference = 9B6BF93B1E27B1F10061B9A7 /* LaunchHelper.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 9B6BF9331E27B1F10061B9A7 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0820; + LastUpgradeCheck = 0820; + ORGANIZATIONNAME = qiuyuzhou; + TargetAttributes = { + 9B6BF93A1E27B1F10061B9A7 = { + CreatedOnToolsVersion = 8.2.1; + DevelopmentTeam = S878RH3PA8; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 9B6BF9361E27B1F10061B9A7 /* Build configuration list for PBXProject "LaunchHelper" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 9B6BF9321E27B1F10061B9A7; + productRefGroup = 9B6BF93C1E27B1F10061B9A7 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 9B6BF93A1E27B1F10061B9A7 /* LaunchHelper */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 9B6BF9391E27B1F10061B9A7 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9B6BF9411E27B1F10061B9A7 /* Assets.xcassets in Resources */, + 9B6BF9441E27B1F10061B9A7 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 9B6BF9371E27B1F10061B9A7 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 9B6BF93F1E27B1F10061B9A7 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 9B6BF9421E27B1F10061B9A7 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 9B6BF9431E27B1F10061B9A7 /* Base */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 9B6BF9461E27B1F10061B9A7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 9B6BF9471E27B1F10061B9A7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.12; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + }; + name = Release; + }; + 9B6BF9491E27B1F10061B9A7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = S878RH3PA8; + INFOPLIST_FILE = LaunchHelper/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.qiuyuzhou.ShadowsocksX-NG.LaunchHelper"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; + }; + name = Debug; + }; + 9B6BF94A1E27B1F10061B9A7 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = S878RH3PA8; + INFOPLIST_FILE = LaunchHelper/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.qiuyuzhou.ShadowsocksX-NG.LaunchHelper"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 9B6BF9361E27B1F10061B9A7 /* Build configuration list for PBXProject "LaunchHelper" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9B6BF9461E27B1F10061B9A7 /* Debug */, + 9B6BF9471E27B1F10061B9A7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 9B6BF9481E27B1F10061B9A7 /* Build configuration list for PBXNativeTarget "LaunchHelper" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 9B6BF9491E27B1F10061B9A7 /* Debug */, + 9B6BF94A1E27B1F10061B9A7 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 9B6BF9331E27B1F10061B9A7 /* Project object */; +} diff --git a/LaunchHelper/LaunchHelper/AppDelegate.swift b/LaunchHelper/LaunchHelper/AppDelegate.swift new file mode 100644 index 0000000..14f7bed --- /dev/null +++ b/LaunchHelper/LaunchHelper/AppDelegate.swift @@ -0,0 +1,48 @@ +// +// AppDelegate.swift +// LaunchHelper +// +// Created by 邱宇舟 on 2017/1/12. +// Copyright © 2017年 qiuyuzhou. All rights reserved. +// + +import Cocoa + +@NSApplicationMain +class AppDelegate: NSObject, NSApplicationDelegate { + + @IBOutlet weak var window: NSWindow! + + + func applicationDidFinishLaunching(_ aNotification: Notification) { + // Insert code here to initialize your application + let mainBundleId = "com.qiuyuzhou.ShadowsocksX-NG" + var alreadyRunning = false; + for app in NSWorkspace.shared().runningApplications { + if app.bundleIdentifier == mainBundleId { + alreadyRunning = true + break + } + } + + if (!alreadyRunning) { + let helperPath: NSString = Bundle.main.bundlePath as NSString; + var pathComponents = helperPath.pathComponents; + pathComponents.removeLast(3); + let mainBundlePath = NSString.path(withComponents: pathComponents); + + if !NSWorkspace.shared().launchApplication(mainBundlePath) { + NSLog("Launch app \(mainBundleId) failed.") + } +// if !NSWorkspace.shared().launchApplication("/Applications/ShadowsocksX-NG.app") { +// NSLog("Launch app \(mainBundleId) failed.") +// } + } + NSApp.terminate(nil); + } + + func applicationWillTerminate(_ aNotification: Notification) { + // Insert code here to tear down your application + } +} + diff --git a/LaunchHelper/LaunchHelper/Assets.xcassets/AppIcon.appiconset/Contents.json b/LaunchHelper/LaunchHelper/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..2db2b1c --- /dev/null +++ b/LaunchHelper/LaunchHelper/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,58 @@ +{ + "images" : [ + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "16x16", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "32x32", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "128x128", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "256x256", + "scale" : "2x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "1x" + }, + { + "idiom" : "mac", + "size" : "512x512", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/LaunchHelper/LaunchHelper/Base.lproj/MainMenu.xib b/LaunchHelper/LaunchHelper/Base.lproj/MainMenu.xib new file mode 100644 index 0000000..ddb5c97 --- /dev/null +++ b/LaunchHelper/LaunchHelper/Base.lproj/MainMenu.xib @@ -0,0 +1,679 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + Default + + + + + + + Left to Right + + + + + + + Right to Left + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LaunchHelper/LaunchHelper/Info.plist b/LaunchHelper/LaunchHelper/Info.plist new file mode 100644 index 0000000..909b70e --- /dev/null +++ b/LaunchHelper/LaunchHelper/Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSBackgroundOnly + + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + Copyright © 2017年 qiuyuzhou. All rights reserved. + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/ShadowsocksX-NG.xcodeproj/project.pbxproj b/ShadowsocksX-NG.xcodeproj/project.pbxproj index 3527917..d04cf9c 100755 --- a/ShadowsocksX-NG.xcodeproj/project.pbxproj +++ b/ShadowsocksX-NG.xcodeproj/project.pbxproj @@ -36,6 +36,8 @@ 9B3FFF4C1D09D8F70019A709 /* install_helper.sh in Resources */ = {isa = PBXBuildFile; fileRef = 9B3FFF4B1D09D8F70019A709 /* install_helper.sh */; }; 9B3FFF4F1D09D9D50019A709 /* ProxyConfHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 9B3FFF4E1D09D9D50019A709 /* ProxyConfHelper.m */; }; 9B3FFF541D09E2D10019A709 /* proxy_conf_helper in Resources */ = {isa = PBXBuildFile; fileRef = 9B3FFF441D09CD3B0019A709 /* proxy_conf_helper */; }; + 9B6BF9521E27B23F0061B9A7 /* LaunchHelper.app in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9B6BF9501E27B1F20061B9A7 /* LaunchHelper.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + 9B6BF9541E27B2570061B9A7 /* ServiceManagement.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B6BF9531E27B2570061B9A7 /* ServiceManagement.framework */; }; 9B9CBCA61E25E1DB00FC61AA /* KcptunProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9B9CBCA51E25E1DB00FC61AA /* KcptunProfile.swift */; }; 9B9CBCA81E26312E00FC61AA /* install_kcptun.sh in Resources */ = {isa = PBXBuildFile; fileRef = 9B9CBCA71E26310E00FC61AA /* install_kcptun.sh */; }; 9B9CBCAA1E2633CB00FC61AA /* kcptun_client in Resources */ = {isa = PBXBuildFile; fileRef = 9B9CBCA91E2633CB00FC61AA /* kcptun_client */; }; @@ -87,6 +89,13 @@ remoteGlobalIDString = 9B3FFF431D09CD3B0019A709; remoteInfo = proxy_conf_helper; }; + 9B6BF94F1E27B1F20061B9A7 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9B6BF94B1E27B1F10061B9A7 /* LaunchHelper.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 9B6BF93B1E27B1F10061B9A7; + remoteInfo = LaunchHelper; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -99,6 +108,16 @@ ); runOnlyForDeploymentPostprocessing = 1; }; + 9B6BF9511E27B2250061B9A7 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = Contents/Library/LoginItems; + dstSubfolderSpec = 1; + files = ( + 9B6BF9521E27B23F0061B9A7 /* LaunchHelper.app in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ @@ -156,6 +175,8 @@ 9B3FFF4E1D09D9D50019A709 /* ProxyConfHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ProxyConfHelper.m; sourceTree = ""; }; 9B3FFF501D09DAEA0019A709 /* proxy_conf_helper_version.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = proxy_conf_helper_version.h; sourceTree = ""; }; 9B3FFF511D09DBA20019A709 /* ShadowsocksX-NG-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ShadowsocksX-NG-Bridging-Header.h"; sourceTree = ""; }; + 9B6BF94B1E27B1F10061B9A7 /* LaunchHelper.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = LaunchHelper.xcodeproj; path = LaunchHelper/LaunchHelper.xcodeproj; sourceTree = ""; }; + 9B6BF9531E27B2570061B9A7 /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/Frameworks/ServiceManagement.framework; sourceTree = SDKROOT; }; 9B9CBCA51E25E1DB00FC61AA /* KcptunProfile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KcptunProfile.swift; sourceTree = ""; }; 9B9CBCA71E26310E00FC61AA /* install_kcptun.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = install_kcptun.sh; sourceTree = ""; }; 9B9CBCA91E2633CB00FC61AA /* kcptun_client */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = kcptun_client; sourceTree = ""; }; @@ -203,6 +224,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 9B6BF9541E27B2570061B9A7 /* ServiceManagement.framework in Frameworks */, 9B3FFF3E1D08D9910019A709 /* SystemConfiguration.framework in Frameworks */, 258E511BA910B0521B24DAB8 /* Pods_ShadowsocksX_NG.framework in Frameworks */, ); @@ -280,6 +302,7 @@ 9B0BFFDC1D0460A70040E62B = { isa = PBXGroup; children = ( + 9B6BF94B1E27B1F10061B9A7 /* LaunchHelper.xcodeproj */, 9B172A601D0ADA5B00B87B9A /* genstrings.py */, 9B0BFFE71D0460A70040E62B /* ShadowsocksX-NG */, 9B0BFFF71D0460A70040E62B /* ShadowsocksX-NGTests */, @@ -370,9 +393,18 @@ path = proxy_conf_helper; sourceTree = ""; }; + 9B6BF94C1E27B1F10061B9A7 /* Products */ = { + isa = PBXGroup; + children = ( + 9B6BF9501E27B1F20061B9A7 /* LaunchHelper.app */, + ); + name = Products; + sourceTree = ""; + }; D3CE66CC039F651F28057DDB /* Frameworks */ = { isa = PBXGroup; children = ( + 9B6BF9531E27B2570061B9A7 /* ServiceManagement.framework */, 9B3FFF3D1D08D9910019A709 /* SystemConfiguration.framework */, 9B3FFF3B1D08D93B0019A709 /* WebKit.framework */, 283ED1A8E9B711AC65670031 /* Pods_ShadowsocksX_NG.framework */, @@ -396,6 +428,7 @@ 9B0BFFE31D0460A70040E62B /* Resources */, 5E160625E3EC80E27DA7EF05 /* [CP] Embed Pods Frameworks */, 3E819BD46B855EDB116A3C70 /* [CP] Copy Pods Resources */, + 9B6BF9511E27B2250061B9A7 /* CopyFiles */, ); buildRules = ( ); @@ -483,6 +516,12 @@ mainGroup = 9B0BFFDC1D0460A70040E62B; productRefGroup = 9B0BFFE61D0460A70040E62B /* Products */; projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 9B6BF94C1E27B1F10061B9A7 /* Products */; + ProjectRef = 9B6BF94B1E27B1F10061B9A7 /* LaunchHelper.xcodeproj */; + }, + ); projectRoot = ""; targets = ( 9B0BFFE41D0460A70040E62B /* ShadowsocksX-NG */, @@ -492,6 +531,16 @@ }; /* End PBXProject section */ +/* Begin PBXReferenceProxy section */ + 9B6BF9501E27B1F20061B9A7 /* LaunchHelper.app */ = { + isa = PBXReferenceProxy; + fileType = wrapper.application; + path = LaunchHelper.app; + remoteRef = 9B6BF94F1E27B1F20061B9A7 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + /* Begin PBXResourcesBuildPhase section */ 9B0BFFE31D0460A70040E62B /* Resources */ = { isa = PBXResourcesBuildPhase; diff --git a/ShadowsocksX-NG/LaunchAtLoginController.h b/ShadowsocksX-NG/LaunchAtLoginController.h index b52c0d7..144f69e 100755 --- a/ShadowsocksX-NG/LaunchAtLoginController.h +++ b/ShadowsocksX-NG/LaunchAtLoginController.h @@ -27,7 +27,5 @@ @property(assign) BOOL launchAtLogin; -- (BOOL) willLaunchAtLogin: (NSURL*) itemURL; -- (void) setLaunchAtLogin: (BOOL) enabled forURL: (NSURL*) itemURL; @end diff --git a/ShadowsocksX-NG/LaunchAtLoginController.m b/ShadowsocksX-NG/LaunchAtLoginController.m index 0f48434..7ba9f7a 100755 --- a/ShadowsocksX-NG/LaunchAtLoginController.m +++ b/ShadowsocksX-NG/LaunchAtLoginController.m @@ -23,24 +23,20 @@ // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "LaunchAtLoginController.h" +#import -static NSString *const StartAtLoginKey = @"launchAtLogin"; +//static NSString *const StartAtLoginKey = @"launchAtLogin"; + +@interface LaunchAtLoginController () { + BOOL _enabled; +} -@interface LaunchAtLoginController () -@property(assign) LSSharedFileListRef loginItems; @end @implementation LaunchAtLoginController -@synthesize loginItems; #pragma mark Change Observing -void sharedFileListDidChange(LSSharedFileListRef inList, void *context) -{ - LaunchAtLoginController *self = (__bridge id) context; - [self willChangeValueForKey:StartAtLoginKey]; - [self didChangeValueForKey:StartAtLoginKey]; -} #pragma mark Initialization @@ -48,76 +44,29 @@ void sharedFileListDidChange(LSSharedFileListRef inList, void *context) { self = [super init]; if (self) { - loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); - LSSharedFileListAddObserver(loginItems, CFRunLoopGetMain(), - (CFStringRef)NSDefaultRunLoopMode, sharedFileListDidChange, (__bridge void *)(self)); + _enabled = [[NSUserDefaults standardUserDefaults] boolForKey: @"LaunchAtLogin"]; } return self; } - (void) dealloc { - LSSharedFileListRemoveObserver(loginItems, CFRunLoopGetMain(), - (CFStringRef)NSDefaultRunLoopMode, sharedFileListDidChange, (__bridge void *)(self)); - CFRelease(loginItems); -} - -#pragma mark Launch List Control - -- (LSSharedFileListItemRef) findItemWithURL: (NSURL*) wantedURL inFileList: (LSSharedFileListRef) fileList -{ - if (wantedURL == NULL || fileList == NULL) - return NULL; - - NSArray *listSnapshot = ((__bridge NSArray *)(LSSharedFileListCopySnapshot(fileList, NULL))); - for (id itemObject in listSnapshot) { - LSSharedFileListItemRef item = (__bridge LSSharedFileListItemRef) itemObject; - UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes; - CFURLRef currentItemURL = NULL; - currentItemURL = LSSharedFileListItemCopyResolvedURL(item, resolutionFlags, NULL); - if (currentItemURL && CFEqual(currentItemURL, (__bridge CFTypeRef)(wantedURL))) { - CFRelease(currentItemURL); - return item; - } - if (currentItemURL) - CFRelease(currentItemURL); - } - - return NULL; -} - -- (BOOL) willLaunchAtLogin: (NSURL*) itemURL -{ - return !![self findItemWithURL:itemURL inFileList:loginItems]; -} - -- (void) setLaunchAtLogin: (BOOL) enabled forURL: (NSURL*) itemURL -{ - LSSharedFileListItemRef appItem = [self findItemWithURL:itemURL inFileList:loginItems]; - if (enabled && !appItem) { - LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemBeforeFirst, - NULL, NULL, (__bridge CFURLRef)itemURL, NULL, NULL); - } else if (!enabled && appItem) - LSSharedFileListItemRemove(loginItems, appItem); -} - -#pragma mark Basic Interface - -- (NSURL*) appURL -{ - return [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]; } - (void) setLaunchAtLogin: (BOOL) enabled { - [self willChangeValueForKey:StartAtLoginKey]; - [self setLaunchAtLogin:enabled forURL:[self appURL]]; - [self didChangeValueForKey:StartAtLoginKey]; + if (SMLoginItemSetEnabled( + (__bridge CFStringRef)@"com.qiuyuzhou.ShadowsocksX-NG.LaunchHelper" + , enabled)) { + _enabled = enabled; + NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; + [defaults setBool: enabled forKey: @"LaunchAtLogin"]; + } } - (BOOL) launchAtLogin { - return [self willLaunchAtLogin:[self appURL]]; + return _enabled; } @end