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.