diff --git a/MacPass/DDHotKey+MacPassAdditions.h b/MacPass/DDHotKey+MacPassAdditions.h index 5ae2442c..3ebcf040 100644 --- a/MacPass/DDHotKey+MacPassAdditions.h +++ b/MacPass/DDHotKey+MacPassAdditions.h @@ -12,11 +12,17 @@ @property (readonly, copy) NSData *keyData; + +/** + Use this method to retrieve the data, since deallocation of a hotkey unregisters it, this could yield unwanted behaviour! + @return data for the default hot key. +*/ ++ (NSData *)hotKeyDataWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags; ++ (NSData *)defaultHotKeyData; + (instancetype)defaultHotKey; + (instancetype)defaultHotKeyWithTask:(DDHotKeyTask)task; - -- (instancetype)initWithKeyData:(NSData *)data task:(DDHotKeyTask)task; -- (instancetype)initWithKeyData:(NSData *)data; ++ (instancetype)hotKeyWithKeyData:(NSData *)data task:(DDHotKeyTask)task; ++ (instancetype)hotKeyWithKeyData:(NSData *)data; @end diff --git a/MacPass/DDHotKey+MacPassAdditions.m b/MacPass/DDHotKey+MacPassAdditions.m index db1fc74d..40ed2281 100644 --- a/MacPass/DDHotKey+MacPassAdditions.m +++ b/MacPass/DDHotKey+MacPassAdditions.m @@ -14,45 +14,48 @@ @implementation DDHotKey (MPKeydata) ++ (NSData *)hotKeyDataWithKeyCode:(unsigned short)keyCode modifierFlags:(NSUInteger)flags { + NSMutableData *data = [[NSMutableData alloc] init]; + NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; + [archiver encodeInt:keyCode forKey:NSStringFromSelector(@selector(keyCode))]; + [archiver encodeInteger:flags forKey:NSStringFromSelector(@selector(modifierFlags))]; + [archiver finishEncoding]; + return [data copy]; +} + ++ (NSData *)defaultHotKeyData { + return [self hotKeyDataWithKeyCode:kVK_ANSI_M modifierFlags:kCGEventFlagMaskControl|kCGEventFlagMaskAlternate]; +} + + (instancetype)defaultHotKey { return [DDHotKey defaultHotKeyWithTask:nil]; } + (instancetype)defaultHotKeyWithTask:(DDHotKeyTask)task { - return [[DDHotKey alloc] initWithKeyData:nil task:task]; + return [DDHotKey hotKeyWithKeyData:nil task:task]; } -- (instancetype)initWithKeyData:(NSData *)data { - self = [self initWithKeyData:data task:nil]; - return self; ++ (instancetype)hotKeyWithKeyData:(NSData *)data { + return [self hotKeyWithKeyData:data task:nil]; } -- (instancetype)initWithKeyData:(NSData *)data task:(DDHotKeyTask)task{ ++ (instancetype)hotKeyWithKeyData:(NSData *)data task:(DDHotKeyTask)task { NSUInteger modifierFlags; unsigned short keyCode; if(!data) { - self = [DDHotKey hotKeyWithKeyCode:kVK_ANSI_M modifierFlags:kCGEventFlagMaskControl|kCGEventFlagMaskAlternate task:task]; + return [DDHotKey hotKeyWithKeyCode:kVK_ANSI_M modifierFlags:kCGEventFlagMaskControl|kCGEventFlagMaskAlternate task:task]; } - else if([self _getKeyCode:&keyCode modifierFlags:&modifierFlags fromData:data]) { - self = [DDHotKey hotKeyWithKeyCode:keyCode modifierFlags:modifierFlags task:task]; + if([self _getKeyCode:&keyCode modifierFlags:&modifierFlags fromData:data]) { + return [DDHotKey hotKeyWithKeyCode:keyCode modifierFlags:modifierFlags task:task]; } - else { - self = nil; - } - return self; + return nil; } - (NSData *)keyData { - NSMutableData *data = [[NSMutableData alloc] init]; - NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; - [archiver encodeInt:self.keyCode forKey:NSStringFromSelector(@selector(keyCode))]; - [archiver encodeInteger:self.modifierFlags forKey:NSStringFromSelector(@selector(modifierFlags))]; - [archiver finishEncoding]; - return [data copy]; + return [self.class hotKeyDataWithKeyCode:self.keyCode modifierFlags:self.modifierFlags]; } - -- (BOOL)_getKeyCode:(unsigned short *)keyCode modifierFlags:(NSUInteger *)modifierFlags fromData:(NSData *)data { ++ (BOOL)_getKeyCode:(unsigned short *)keyCode modifierFlags:(NSUInteger *)modifierFlags fromData:(NSData *)data { if(keyCode == NULL || modifierFlags == NULL || data == nil) { return NO; } diff --git a/MacPass/MPAutotypeDaemon.m b/MacPass/MPAutotypeDaemon.m index 715bf69e..db48fc4c 100644 --- a/MacPass/MPAutotypeDaemon.m +++ b/MacPass/MPAutotypeDaemon.m @@ -147,16 +147,32 @@ static MPAutotypeDaemon *_sharedInstance; return; // We do not perform Autotype on ourselves } - NSArray *documents = [self _findAutotypeDocuments]; + /* find autotype documents */ + NSArray *documents = [NSApp orderedDocuments]; + /* No open document, inform the user and return without any action */ if(documents.count == 0) { - /* We do not have a document. This can be - a) there is none - nothing happens - b) there is at least one, but locked - we get called again after the document has been unlocked - */ + NSUserNotification *notification = [[NSUserNotification alloc] init]; + notification.title = NSApp.applicationName; + notification.informativeText = NSLocalizedString(@"AUTOTYPE_OVERLAY_NO_DOCUMENTS", ""); + [[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification]; return; } + NSPredicate *filterPredicate = [NSPredicate predicateWithBlock:^BOOL(id _Nonnull evaluatedObject, NSDictionary * _Nullable bindings) { + MPDocument *document = evaluatedObject; + return !document.encrypted;}]; + NSArray *unlockedDocuments = [documents filteredArrayUsingPredicate:filterPredicate]; + /* We look for all unlocked documents, if all open documents are locked, we pop the front most and try to search again */ + if(unlockedDocuments.count == 0) { + [NSApp activateIgnoringOtherApps:YES]; + [NSApp.mainWindow makeKeyAndOrderFront:self]; + /* show the actual document window to the user */ + [documents.firstObject showWindows]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didUnlockDatabase:) name:MPDocumentDidUnlockDatabaseNotification object:nil]; + return; // wait for the unlock to happen + } + MPAutotypeContext *context = [self _autotypeContextForDocuments:documents forWindowTitle:self.targetWindowTitle preferredEntry:entryOrNil]; - /* TODO: that's popping up if the mulit seleciton dialog goes up! */ + /* TODO: that's popping up if the mulit selection dialog goes up! */ if(!entryOrNil) { NSUserNotification *notification = [[NSUserNotification alloc] init]; notification.title = NSApp.applicationName; @@ -171,22 +187,6 @@ static MPAutotypeDaemon *_sharedInstance; [self _performAutotypeForContext:context]; } -- (NSArray *)_findAutotypeDocuments { - - NSArray *documents = [NSApp orderedDocuments]; - NSPredicate *filterPredicate = [NSPredicate predicateWithBlock:^BOOL(id _Nonnull evaluatedObject, NSDictionary * _Nullable bindings) { - MPDocument *document = evaluatedObject; - return !document.encrypted;}]; - NSArray *unlockedDocuments = [documents filteredArrayUsingPredicate:filterPredicate]; - /* We look for all unlocked documents, if all open documents are locked, we pop the front most and try to search again */ - if(unlockedDocuments.count == 0 && documents.count > 0) { - [NSApp activateIgnoringOtherApps:YES]; - [NSApp.mainWindow makeKeyAndOrderFront:self]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_didUnlockDatabase:) name:MPDocumentDidUnlockDatabaseNotification object:nil]; - } - return unlockedDocuments; -} - - (MPAutotypeContext *)_autotypeContextForDocuments:(NSArray *)documents forWindowTitle:(NSString *)windowTitle preferredEntry:(KPKEntry *)entry { /* Query the document to generate a autotype command list for the window title @@ -230,22 +230,18 @@ static MPAutotypeDaemon *_sharedInstance; #pragma mark - #pragma mark Hotkey Registration - (void)_registerHotKey { + if(!self.hotKeyData) { + return; + } __weak MPAutotypeDaemon *welf = self; DDHotKeyTask aTask = ^(NSEvent *event) { [welf _didPressHotKey]; }; - DDHotKey *storedHotkey; - if(nil == self.hotKeyData) { - storedHotkey = [DDHotKey defaultHotKeyWithTask:aTask]; - } - else { - storedHotkey = [[DDHotKey alloc] initWithKeyData:self.hotKeyData task:aTask]; - } - self.registredHotKey = [[DDHotKeyCenter sharedHotKeyCenter] registerHotKey:storedHotkey]; + self.registredHotKey = [[DDHotKeyCenter sharedHotKeyCenter] registerHotKey:[DDHotKey hotKeyWithKeyData:self.hotKeyData task:aTask]]; } - (void)_unregisterHotKey { - if(nil != self.registredHotKey) { + if(self.registredHotKey) { [[DDHotKeyCenter sharedHotKeyCenter] unregisterHotKey:self.registredHotKey]; self.registredHotKey = nil; } diff --git a/MacPass/MPIntegrationSettingsController.m b/MacPass/MPIntegrationSettingsController.m index 895d0042..9c417465 100644 --- a/MacPass/MPIntegrationSettingsController.m +++ b/MacPass/MPIntegrationSettingsController.m @@ -58,7 +58,7 @@ } - (void)willShowTab { - _hotKey = [[DDHotKey alloc] initWithKeyData:[[NSUserDefaults standardUserDefaults] dataForKey:kMPSettingsKeyGlobalAutotypeKeyDataKey]]; + _hotKey = [DDHotKey hotKeyWithKeyData:[[NSUserDefaults standardUserDefaults] dataForKey:kMPSettingsKeyGlobalAutotypeKeyDataKey]]; /* Change any invalid hotkeys to valid ones? */ self.hotKeyTextField.hotKey = self.hotKey; } diff --git a/MacPass/MPSettingsHelper.m b/MacPass/MPSettingsHelper.m index b04243ce..a0bb06d5 100644 --- a/MacPass/MPSettingsHelper.m +++ b/MacPass/MPSettingsHelper.m @@ -110,7 +110,7 @@ NSString *const kMPDeprecatedSettingsKeyDefaultPasswordRounds = @"Ke kMPSettingsKeyRememberKeyFilesForDatabases: @NO, kMPSettingsKeySendCommandForControlKey: @YES, kMPSettingsKeyEnableGlobalAutotype: @NO, - kMPSettingsKeyGlobalAutotypeKeyDataKey: [[DDHotKey defaultHotKey] keyData], + kMPSettingsKeyGlobalAutotypeKeyDataKey: [DDHotKey defaultHotKeyData], kMPSettingsKeyDefaultGlobalAutotypeSequence: @"{USERNAME}{TAB}{PASSWORD}{ENTER}", kMPSettingsKeyAutotypeMatchTitle: @YES, kMPSettingsKeyAutotypeMatchURL: @NO, diff --git a/MacPass/de.lproj/Localizable.strings b/MacPass/de.lproj/Localizable.strings index 1429fa87..ec6fb88f 100644 Binary files a/MacPass/de.lproj/Localizable.strings and b/MacPass/de.lproj/Localizable.strings differ diff --git a/MacPass/en.lproj/Localizable.strings b/MacPass/en.lproj/Localizable.strings index 7c316199..d8d1f641 100644 Binary files a/MacPass/en.lproj/Localizable.strings and b/MacPass/en.lproj/Localizable.strings differ diff --git a/MacPass/fr.lproj/Localizable.strings b/MacPass/fr.lproj/Localizable.strings index abb3da39..8693e62d 100644 Binary files a/MacPass/fr.lproj/Localizable.strings and b/MacPass/fr.lproj/Localizable.strings differ diff --git a/MacPass/it.lproj/Localizable.strings b/MacPass/it.lproj/Localizable.strings index 500a3d72..3b37c573 100644 Binary files a/MacPass/it.lproj/Localizable.strings and b/MacPass/it.lproj/Localizable.strings differ diff --git a/MacPass/nl.lproj/Localizable.strings b/MacPass/nl.lproj/Localizable.strings index cee03724..9965b161 100644 Binary files a/MacPass/nl.lproj/Localizable.strings and b/MacPass/nl.lproj/Localizable.strings differ diff --git a/MacPass/ru.lproj/Localizable.strings b/MacPass/ru.lproj/Localizable.strings index 5d672103..64c9406e 100644 Binary files a/MacPass/ru.lproj/Localizable.strings and b/MacPass/ru.lproj/Localizable.strings differ diff --git a/MacPass/zh-Hans.lproj/Localizable.strings b/MacPass/zh-Hans.lproj/Localizable.strings index d82179ae..ef2175c0 100644 Binary files a/MacPass/zh-Hans.lproj/Localizable.strings and b/MacPass/zh-Hans.lproj/Localizable.strings differ