--- /dev/null
+//
+// NSRunningApplication+NJPossibleNames.h
+// Enjoyable
+//
+// Created by Joe Wreschnig on 3/8/13.
+//
+//
+
+#import <Cocoa/Cocoa.h>
+
+@interface NSRunningApplication (NJPossibleNames)
+
+- (NSArray *)possibleMappingNames;
+ // Return a list of mapping names this application could match.
+
+- (NSString *)bestMappingName;
+ // Return the best mapping name, taking into account ways in which
+ // application names are often broken.
+
+@end
--- /dev/null
+//
+// NSRunningApplication+NJPossibleNames.m
+// Enjoyable
+//
+// Created by Joe Wreschnig on 3/8/13.
+//
+//
+
+#import "NSRunningApplication+NJPossibleNames.h"
+
+@implementation NSRunningApplication (NJPossibleNames)
+
+- (NSArray *)possibleMappingNames {
+ NSMutableArray *names = [[NSMutableArray alloc] initWithCapacity:4];
+ if (self.bundleIdentifier)
+ [names addObject:self.bundleIdentifier];
+ if (self.localizedName)
+ [names addObject:self.localizedName];
+ if (self.bundleURL)
+ [names addObject:[self.bundleURL.lastPathComponent stringByDeletingPathExtension]];
+ if (self.executableURL)
+ [names addObject:self.executableURL.lastPathComponent];
+ return names;
+}
+
+- (NSString *)bestMappingName {
+ // A number of Flash applications all use the generic Flash bundle
+ // ID and localized name, but they name their bundle file and
+ // executable correctly. Don't want to fall back to those IDs
+ // unless we absolutely have to.
+ NSArray *genericBundles = @[
+ @"com.macromedia.Flash Player Debugger.app",
+ @"com.macromedia.Flash Player.app",
+ ];
+ BOOL probablyWrong = [genericBundles containsObject:self.bundleIdentifier];
+ if (!probablyWrong && self.localizedName)
+ return self.localizedName;
+ else if (!probablyWrong && self.bundleIdentifier)
+ return self.bundleIdentifier;
+ else if (self.bundleURL)
+ return [self.bundleURL.lastPathComponent stringByDeletingPathExtension];
+ else if (self.executableURL)
+ return self.executableURL.lastPathComponent;
+ else if (self.localizedName)
+ return self.localizedName;
+ else if (self.bundleIdentifier)
+ return self.bundleIdentifier;
+ else
+ return @"@Application";
+}
+
+@end
- (void)didSwitchApplication:(NSNotification *)note {
NSRunningApplication *activeApp = note.userInfo[NSWorkspaceApplicationKey];
- NSString *name = activeApp.localizedName;
- if (!name)
- name = activeApp.bundleIdentifier;
- if (name && ![name isEqualToString:NSRunningApplication.currentApplication.localizedName])
- [self.mappingsController activateMappingForProcess:name];
+ if (activeApp)
+ [self.mappingsController activateMappingForProcess:activeApp];
}
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
- (NJMapping *)objectAtIndexedSubscript:(NSUInteger)idx;
- (void)addMappingWithContentsOfURL:(NSURL *)url;
- (void)activateMapping:(NJMapping *)mapping;
-- (void)activateMappingForProcess:(NSString *)processName;
+- (void)activateMappingForProcess:(NSRunningApplication *)app;
- (void)save;
- (void)load;
count:len];
}
-- (void)activateMappingForProcess:(NSString *)processName {
- if ([manualMapping.name.lowercaseString isEqualToString:@"@application"]) {
- manualMapping.name = processName;
- [self mappingsChanged];
- } else {
- NJMapping *oldMapping = manualMapping;
- NJMapping *newMapping = self[processName];
- if (!newMapping)
- newMapping = oldMapping;
- if (newMapping != _currentMapping)
- [self activateMapping:newMapping];
- manualMapping = oldMapping;
+- (void)activateMappingForProcess:(NSRunningApplication *)app {
+ NJMapping *oldMapping = manualMapping;
+ NSArray *names = app.possibleMappingNames;
+ BOOL found = NO;
+ for (NSString *name in names) {
+ NJMapping *mapping = self[name];
+ if (mapping) {
+ [self activateMapping:self[name]];
+ found = YES;
+ break;
+ }
+ }
+
+ if (!found) {
+ [self activateMapping:oldMapping];
+ if ([oldMapping.name.lowercaseString isEqualToString:@"@application"]) {
+ oldMapping.name = app.bestMappingName;
+ [self mappingsChanged];
+ }
}
+ manualMapping = oldMapping;
}
- (void)updateInterfaceForCurrentMapping {
8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
D594BF000FAE7397007A85F2 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D594BEFF0FAE7397007A85F2 /* IOKit.framework */; };
EE6A122E16E8F46300EDBD32 /* Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = EE6A122D16E8F46300EDBD32 /* Icon.icns */; };
+ EEE73B1616EA42E5009D9D99 /* NSRunningApplication+NJPossibleNames.m in Sources */ = {isa = PBXBuildFile; fileRef = EEE73B1516EA42E5009D9D99 /* NSRunningApplication+NJPossibleNames.m */; };
EEF17D1916E8E21A00D7DC4D /* com.yukkurigames.Enjoyable.mapping.icns in Resources */ = {isa = PBXBuildFile; fileRef = EEF17D1716E8E21A00D7DC4D /* com.yukkurigames.Enjoyable.mapping.icns */; };
EEF17D1F16E8E23A00D7DC4D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = EEF17D1B16E8E23A00D7DC4D /* InfoPlist.strings */; };
EEF17D2016E8E23A00D7DC4D /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = EEF17D1D16E8E23A00D7DC4D /* MainMenu.xib */; };
8D1107320486CEB800E47090 /* Enjoyable.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Enjoyable.app; sourceTree = BUILT_PRODUCTS_DIR; };
D594BEFF0FAE7397007A85F2 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = "<absolute>"; };
EE6A122D16E8F46300EDBD32 /* Icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = Icon.icns; sourceTree = "<group>"; };
+ EEE73B1416EA42E5009D9D99 /* NSRunningApplication+NJPossibleNames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSRunningApplication+NJPossibleNames.h"; path = "Categories/NSRunningApplication+NJPossibleNames.h"; sourceTree = "<group>"; };
+ EEE73B1516EA42E5009D9D99 /* NSRunningApplication+NJPossibleNames.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSRunningApplication+NJPossibleNames.m"; path = "Categories/NSRunningApplication+NJPossibleNames.m"; sourceTree = "<group>"; };
EEF17D1716E8E21A00D7DC4D /* com.yukkurigames.Enjoyable.mapping.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = com.yukkurigames.Enjoyable.mapping.icns; path = Resources/com.yukkurigames.Enjoyable.mapping.icns; sourceTree = "<group>"; };
EEF17D1C16E8E23A00D7DC4D /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = Resources/English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
EEF17D1E16E8E23A00D7DC4D /* English */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = English; path = Resources/English.lproj/MainMenu.xib; sourceTree = "<group>"; };
EEF17D3016E8E2E100D7DC4D /* NSString+FixFilename.m */,
EEF17D3116E8E2E100D7DC4D /* NSView+FirstResponder.h */,
EEF17D3216E8E2E100D7DC4D /* NSView+FirstResponder.m */,
+ EEE73B1416EA42E5009D9D99 /* NSRunningApplication+NJPossibleNames.h */,
+ EEE73B1516EA42E5009D9D99 /* NSRunningApplication+NJPossibleNames.m */,
);
name = Categories;
sourceTree = "<group>";
EEF17D6A16E8E2EF00D7DC4D /* NJOutputMouseButton.m in Sources */,
EEF17D6B16E8E2EF00D7DC4D /* NJOutputMouseMove.m in Sources */,
EEF17D6C16E8E2EF00D7DC4D /* NJOutputMouseScroll.m in Sources */,
+ EEE73B1616EA42E5009D9D99 /* NSRunningApplication+NJPossibleNames.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
#import "NSMutableArray+MoveObject.h"
#import "NSFileManager+UniqueNames.h"
#import "NSString+FixFilename.h"
+#import "NSRunningApplication+NJPossibleNames.h"