mirror of
https://github.com/MacPass/MacPass.git
synced 2025-12-13 21:42:32 +00:00
Reworked use of DDHotKey to prevent unwanted deregistration.
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<NSString *,id> * _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<MPDocument *> *)_findAutotypeDocuments {
|
||||
|
||||
NSArray *documents = [NSApp orderedDocuments];
|
||||
NSPredicate *filterPredicate = [NSPredicate predicateWithBlock:^BOOL(id _Nonnull evaluatedObject, NSDictionary<NSString *,id> * _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<MPDocument *> *)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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user