From f8ae7787fe3fe272eaf04586e3007339c907fb33 Mon Sep 17 00:00:00 2001 From: Joe Wreschnig Date: Wed, 13 Mar 2013 18:34:41 +0100 Subject: [PATCH] Support relaunching in the background as part of resume/launch items. --- Categories/NSRunningApplication+LoginItem.h | 19 +++++ Categories/NSRunningApplication+LoginItem.m | 89 +++++++++++++++++++++ Classes/EnjoyableApplicationDelegate.m | 14 +++- Enjoyable.xcodeproj/project.pbxproj | 6 ++ Info.plist | 2 +- Other Sources/Enjoyable_Prefix.pch | 1 + Resources/English.lproj/MainMenu.xib | 6 +- Website/index.html | 1 + 8 files changed, 132 insertions(+), 6 deletions(-) create mode 100644 Categories/NSRunningApplication+LoginItem.h create mode 100644 Categories/NSRunningApplication+LoginItem.m diff --git a/Categories/NSRunningApplication+LoginItem.h b/Categories/NSRunningApplication+LoginItem.h new file mode 100644 index 0000000..da5dd19 --- /dev/null +++ b/Categories/NSRunningApplication+LoginItem.h @@ -0,0 +1,19 @@ +// +// NSRunningApplication+LoginItem.h +// Enjoyable +// +// Created by Joe Wreschnig on 3/13/13. +// +// + +#import + +@interface NSRunningApplication (LoginItem) + // Don't be a jerk. Ask the user before doing this. + +- (BOOL)isLoginItem; +- (void)addToLoginItems; +- (void)removeFromLoginItems; +- (BOOL)wasLaunchedAsLoginItemOrResume; + +@end diff --git a/Categories/NSRunningApplication+LoginItem.m b/Categories/NSRunningApplication+LoginItem.m new file mode 100644 index 0000000..53a9521 --- /dev/null +++ b/Categories/NSRunningApplication+LoginItem.m @@ -0,0 +1,89 @@ +// +// NSApplication+LoginItem.m +// Enjoyable +// +// Created by Joe Wreschnig on 3/13/13. +// +// + +#import "NSRunningApplication+LoginItem.h" + +#import + +static const UInt32 RESOLVE_FLAGS = kLSSharedFileListNoUserInteraction + | kLSSharedFileListDoNotMountVolumes; + +@implementation NSRunningApplication (LoginItem) + +- (BOOL)isLoginItem { + LSSharedFileListRef loginItems = LSSharedFileListCreate( + NULL, kLSSharedFileListSessionLoginItems, NULL); + NSURL *myURL = self.bundleURL; + BOOL found = NO; + UInt32 seed = 0; + NSArray *currentLoginItems = CFBridgingRelease( + LSSharedFileListCopySnapshot(loginItems, &seed)); + for (id obj in currentLoginItems) { + LSSharedFileListItemRef item = (__bridge LSSharedFileListItemRef)obj; + CFURLRef itemURL = NULL; + if (!LSSharedFileListItemResolve(item, RESOLVE_FLAGS, &itemURL, NULL)) { + found = CFEqual(itemURL, (__bridge CFURLRef)myURL); + CFRelease(itemURL); + } + if (found) + break; + } + CFRelease(loginItems); + return found; +} + +- (void)addToLoginItems { + if (!self.isLoginItem) { + NSURL *myURL = self.bundleURL; + LSSharedFileListRef loginItems = LSSharedFileListCreate( + NULL, kLSSharedFileListSessionLoginItems, NULL); + LSSharedFileListInsertItemURL( + loginItems, kLSSharedFileListItemBeforeFirst, + NULL, NULL, (__bridge CFURLRef)myURL, NULL, NULL); + CFRelease(loginItems); + } +} + +- (void)removeFromLoginItems { + LSSharedFileListRef loginItems = LSSharedFileListCreate( + NULL, kLSSharedFileListSessionLoginItems, NULL); + NSURL *myURL = self.bundleURL; + UInt32 seed = 0; + NSArray *currentLoginItems = CFBridgingRelease( + LSSharedFileListCopySnapshot(loginItems, &seed)); + for (id obj in currentLoginItems) { + LSSharedFileListItemRef item = (__bridge LSSharedFileListItemRef)obj; + CFURLRef itemURL = NULL; + if (!LSSharedFileListItemResolve(item, RESOLVE_FLAGS, &itemURL, NULL)) { + if (CFEqual(itemURL, (__bridge CFURLRef)myURL)) + LSSharedFileListItemRemove(loginItems, item); + CFRelease(itemURL); + } + } + CFRelease(loginItems); +} + +- (BOOL)wasLaunchedAsLoginItemOrResume { + ProcessSerialNumber psn = { 0, kCurrentProcess }; + NSDictionary *processInfo = CFBridgingRelease( + ProcessInformationCopyDictionary( + &psn, kProcessDictionaryIncludeAllInformationMask)); + long long parent = [processInfo[@"ParentPSN"] longLongValue]; + ProcessSerialNumber parentPsn = { + (parent >> 32) & 0x00000000FFFFFFFFLL, + parent & 0x00000000FFFFFFFFLL + }; + + NSDictionary *parentInfo = CFBridgingRelease( + ProcessInformationCopyDictionary( + &parentPsn, kProcessDictionaryIncludeAllInformationMask)); + return [parentInfo[@"FileCreator"] isEqualToString:@"lgnw"]; +} + + +@end diff --git a/Classes/EnjoyableApplicationDelegate.m b/Classes/EnjoyableApplicationDelegate.m index f151399..f02ec90 100644 --- a/Classes/EnjoyableApplicationDelegate.m +++ b/Classes/EnjoyableApplicationDelegate.m @@ -48,7 +48,14 @@ } - (void)applicationDidFinishLaunching:(NSNotification *)notification { - [window makeKeyAndOrderFront:nil]; + if (NSRunningApplication.currentApplication.wasLaunchedAsLoginItemOrResume + && [NSUserDefaults.standardUserDefaults boolForKey:@"hidden in status item"]) { + [self transformIntoElement:self]; + NSApplication *app = notification.object; + [app deactivate]; + } else { + [window makeKeyAndOrderFront:nil]; + } } - (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication @@ -65,15 +72,18 @@ [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(transformIntoElement:) object:self]; + [NSUserDefaults.standardUserDefaults setBool:NO forKey:@"hidden in status item"]; } - (void)applicationWillBecomeActive:(NSNotification *)notification { - [self restoreToForeground:notification]; + if (window.isVisible) + [self restoreToForeground:notification]; } - (void)transformIntoElement:(id)sender { ProcessSerialNumber psn = { 0, kCurrentProcess }; TransformProcessType(&psn, kProcessTransformToUIElementApplication); + [NSUserDefaults.standardUserDefaults setBool:YES forKey:@"hidden in status item"]; } - (void)flashStatusItem { diff --git a/Enjoyable.xcodeproj/project.pbxproj b/Enjoyable.xcodeproj/project.pbxproj index eee41a1..d428220 100644 --- a/Enjoyable.xcodeproj/project.pbxproj +++ b/Enjoyable.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ EE3D897F16EA817E00596D1F /* Status Menu Icon Disabled.png in Resources */ = {isa = PBXBuildFile; fileRef = EE3D897D16EA817E00596D1F /* Status Menu Icon Disabled.png */; }; EE3D898016EA817E00596D1F /* Status Menu Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = EE3D897E16EA817E00596D1F /* Status Menu Icon.png */; }; EE6A122E16E8F46300EDBD32 /* Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = EE6A122D16E8F46300EDBD32 /* Icon.icns */; }; + EE8455DD16F0E46B00F32A01 /* NSRunningApplication+LoginItem.m in Sources */ = {isa = PBXBuildFile; fileRef = EE8455DC16F0E46B00F32A01 /* NSRunningApplication+LoginItem.m */; }; EED4CE6E16ED692400C65AA8 /* NJMappingMenuController.m in Sources */ = {isa = PBXBuildFile; fileRef = EED4CE6D16ED692400C65AA8 /* NJMappingMenuController.m */; }; EED4CE7716EE195100C65AA8 /* Sparkle.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EED4CE7616EE195100C65AA8 /* Sparkle.framework */; }; EED4CE7816EE195B00C65AA8 /* Sparkle.framework in Copy Sparkle Framework */ = {isa = PBXBuildFile; fileRef = EED4CE7616EE195100C65AA8 /* Sparkle.framework */; }; @@ -78,6 +79,8 @@ EE3D897D16EA817E00596D1F /* Status Menu Icon Disabled.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Status Menu Icon Disabled.png"; path = "Resources/Status Menu Icon Disabled.png"; sourceTree = ""; }; EE3D897E16EA817E00596D1F /* Status Menu Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Status Menu Icon.png"; path = "Resources/Status Menu Icon.png"; sourceTree = ""; }; EE6A122D16E8F46300EDBD32 /* Icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = Icon.icns; sourceTree = ""; }; + EE8455DB16F0E46B00F32A01 /* NSRunningApplication+LoginItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSRunningApplication+LoginItem.h"; path = "Categories/NSRunningApplication+LoginItem.h"; sourceTree = ""; }; + EE8455DC16F0E46B00F32A01 /* NSRunningApplication+LoginItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSRunningApplication+LoginItem.m"; path = "Categories/NSRunningApplication+LoginItem.m"; sourceTree = ""; }; EED4CE6C16ED692400C65AA8 /* NJMappingMenuController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NJMappingMenuController.h; path = Classes/NJMappingMenuController.h; sourceTree = ""; }; EED4CE6D16ED692400C65AA8 /* NJMappingMenuController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = NJMappingMenuController.m; path = Classes/NJMappingMenuController.m; sourceTree = ""; }; EED4CE7616EE195100C65AA8 /* Sparkle.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Sparkle.framework; sourceTree = ""; }; @@ -283,6 +286,8 @@ EE1D5F8B16E403D600749C36 /* Categories */ = { isa = PBXGroup; children = ( + EE8455DB16F0E46B00F32A01 /* NSRunningApplication+LoginItem.h */, + EE8455DC16F0E46B00F32A01 /* NSRunningApplication+LoginItem.m */, EEF17D2716E8E2E100D7DC4D /* NSError+Description.h */, EEF17D2816E8E2E100D7DC4D /* NSError+Description.m */, EEF17D2916E8E2E100D7DC4D /* NSFileManager+UniqueNames.h */, @@ -436,6 +441,7 @@ EED4CE6E16ED692400C65AA8 /* NJMappingMenuController.m in Sources */, EEE703DC16F089FE002FDD69 /* NJHIDManager.m in Sources */, EEE703DE16F0B3F6002FDD69 /* NJInputPathElement.m in Sources */, + EE8455DD16F0E46B00F32A01 /* NSRunningApplication+LoginItem.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Info.plist b/Info.plist index f3cc683..6191eaa 100644 --- a/Info.plist +++ b/Info.plist @@ -46,7 +46,7 @@ CFBundleSignature ???? CFBundleVersion - 248 + 258 LSApplicationCategoryType public.app-category.utilities NSHumanReadableCopyright diff --git a/Other Sources/Enjoyable_Prefix.pch b/Other Sources/Enjoyable_Prefix.pch index 61d6aee..b0d1f40 100644 --- a/Other Sources/Enjoyable_Prefix.pch +++ b/Other Sources/Enjoyable_Prefix.pch @@ -15,3 +15,4 @@ #import "NSFileManager+UniqueNames.h" #import "NSString+FixFilename.h" #import "NSRunningApplication+NJPossibleNames.h" +#import "NSRunningApplication+LoginItem.h" diff --git a/Resources/English.lproj/MainMenu.xib b/Resources/English.lproj/MainMenu.xib index c63659b..98b5cef 100644 --- a/Resources/English.lproj/MainMenu.xib +++ b/Resources/English.lproj/MainMenu.xib @@ -567,7 +567,7 @@ aW5nLg {232, 321} - + YES NO YES @@ -697,7 +697,7 @@ aW5nLg {234, 323} - + 150034 @@ -3026,7 +3026,7 @@ aW5nLg com.apple.InterfaceBuilder.CocoaPlugin {{114, 276}, {770, 487}} - + com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin diff --git a/Website/index.html b/Website/index.html index 6525b71..03d3468 100644 --- a/Website/index.html +++ b/Website/index.html @@ -51,6 +51,7 @@ them.