Reworked use of DDHotKey to prevent unwanted deregistration.

This commit is contained in:
michael starke
2017-01-03 14:50:08 +01:00
parent 0d5dcc4aad
commit d912285919
12 changed files with 61 additions and 56 deletions

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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.