mirror of
https://github.com/MacPass/MacPass.git
synced 2025-12-23 17:29:28 +00:00
Enhanced Autotype
Autotype now looks in all open documents for matches Autotype now uses the same matching as KeePass Settings for autotype are now enabled in the UI since they are used now Signed-off-by: michael starke <michael.starke@hicknhack-software.com>
This commit is contained in:
@@ -109,8 +109,8 @@ NSString *const kMPProcessIdentifierKey = @"kMPProcessIdentifierKey";
|
||||
#pragma mark -
|
||||
#pragma mark Actions
|
||||
- (void)performAutotypeWithSelectedMatch:(id)sender {
|
||||
NSMenuItem *item = [self.matchSelectionButton selectedItem];
|
||||
MPAutotypeContext *context = [item representedObject];
|
||||
NSMenuItem *item = self.matchSelectionButton.selectedItem;
|
||||
MPAutotypeContext *context = item.representedObject;
|
||||
[self.matchSelectionWindow orderOut:self];
|
||||
[self _performAutotypeForContext:context];
|
||||
}
|
||||
@@ -131,17 +131,16 @@ NSString *const kMPProcessIdentifierKey = @"kMPProcessIdentifierKey";
|
||||
return; // We do not perform Autotype on ourselves
|
||||
}
|
||||
|
||||
MPDocument *document = [self _findAutotypeDocument];
|
||||
if(!document) {
|
||||
NSArray *documents = [self _findAutotypeDocuments];
|
||||
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
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
MPAutotypeContext *context = [self _autotypeContextInDocument:document forWindowTitle:self.targetWindowTitle preferredEntry:entryOrNil];
|
||||
/* TODO: that's popping up if the multi selection dialog goes up! */
|
||||
MPAutotypeContext *context = [self _autotypeContextForDocuments:documents forWindowTitle:self.targetWindowTitle preferredEntry:entryOrNil];
|
||||
/* TODO: that's popping up if the mulit seleciton dialog goes up! */
|
||||
if(!entryOrNil) {
|
||||
NSImage *appIcon = [[NSApplication sharedApplication] applicationIconImage];
|
||||
NSString *label = context ? NSLocalizedString(@"AUTOTYPE_OVERLAY_SINGLE_MATCH", "") : NSLocalizedString(@"AUTOTYPE_OVERLAY_NO_MATCH", "");
|
||||
@@ -150,36 +149,40 @@ NSString *const kMPProcessIdentifierKey = @"kMPProcessIdentifierKey";
|
||||
[self _performAutotypeForContext:context];
|
||||
}
|
||||
|
||||
- (MPDocument *)_findAutotypeDocument {
|
||||
- (NSArray<MPDocument *> *)_findAutotypeDocuments {
|
||||
|
||||
NSArray *documents = [NSApp orderedDocuments];
|
||||
MPDocument *currentDocument = nil;
|
||||
for(MPDocument *openDocument in documents) {
|
||||
if(NO == openDocument.encrypted) {
|
||||
currentDocument = openDocument;
|
||||
break;
|
||||
}
|
||||
}
|
||||
BOOL hasOpenDocuments = [documents count] > 0;
|
||||
if(!currentDocument && hasOpenDocuments) {
|
||||
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 currentDocument;
|
||||
return unlockedDocuments;
|
||||
}
|
||||
|
||||
- (MPAutotypeContext *)_autotypeContextInDocument:(MPDocument *)document forWindowTitle:(NSString *)windowTitle preferredEntry:(KPKEntry *)entry {
|
||||
- (MPAutotypeContext *)_autotypeContextForDocuments:(NSArray<MPDocument *> *)documents forWindowTitle:(NSString *)windowTitle preferredEntry:(KPKEntry *)entry {
|
||||
/*
|
||||
Query the document to generate a autotype command list for the window title
|
||||
We do not care where this came form, just get the autotype commands
|
||||
*/
|
||||
NSArray *autotypeCandidates = [document autotypContextsForWindowTitle:windowTitle preferredEntry:entry];
|
||||
NSUInteger candidates = [autotypeCandidates count];
|
||||
NSMutableArray *autotypeCandidates = [[NSMutableArray alloc] init];
|
||||
for(MPDocument *document in documents) {
|
||||
NSArray *contexts = [document autotypContextsForWindowTitle:windowTitle preferredEntry:entry];
|
||||
if(contexts ) {
|
||||
[autotypeCandidates addObjectsFromArray:contexts];
|
||||
}
|
||||
}
|
||||
NSUInteger candidates = autotypeCandidates.count;
|
||||
if(candidates == 0) {
|
||||
return nil;
|
||||
}
|
||||
if(candidates == 1 ) {
|
||||
return [autotypeCandidates lastObject];
|
||||
return autotypeCandidates.lastObject;
|
||||
}
|
||||
[self _presentSelectionWindow:autotypeCandidates];
|
||||
return nil; // Nothing to do, we get called back by the window
|
||||
@@ -191,11 +194,11 @@ NSString *const kMPProcessIdentifierKey = @"kMPProcessIdentifierKey";
|
||||
}
|
||||
if([self _orderApplicationToFront:self.targetPID]) {
|
||||
/* Sleep a bit after the app was activated */
|
||||
/* TODO - we can use a saver way and use a notification to check if the app actually was activated */
|
||||
/* TODO - we can use a saver way and use a notification to chekc if the app actally was activated */
|
||||
usleep(1 * NSEC_PER_MSEC);
|
||||
}
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
NSArray *commands = [MPAutotypeCommand commandsForContext:context];
|
||||
NSArray<MPAutotypeCommand *> *commands = [MPAutotypeCommand commandsForContext:context];
|
||||
for(MPAutotypeCommand *command in commands) {
|
||||
[command execute];
|
||||
}
|
||||
@@ -230,7 +233,7 @@ NSString *const kMPProcessIdentifierKey = @"kMPProcessIdentifierKey";
|
||||
NSArray *currentWindows = CFBridgingRelease(CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID));
|
||||
for(NSDictionary *windowDict in currentWindows) {
|
||||
NSString *windowTitle = windowDict[(NSString *)kCGWindowName];
|
||||
if([windowTitle length] <= 0) {
|
||||
if(windowTitle.length <= 0) {
|
||||
continue;
|
||||
}
|
||||
NSNumber *processId = windowDict[(NSString *)kCGWindowOwnerPID];
|
||||
@@ -247,12 +250,12 @@ NSString *const kMPProcessIdentifierKey = @"kMPProcessIdentifierKey";
|
||||
- (void)_presentSelectionWindow:(NSArray *)candidates {
|
||||
if(!self.matchSelectionWindow) {
|
||||
[[NSBundle mainBundle] loadNibNamed:@"AutotypeCandidateSelectionWindow" owner:self topLevelObjects:nil];
|
||||
[self.matchSelectionWindow setLevel:NSFloatingWindowLevel];
|
||||
self.matchSelectionWindow.level = NSFloatingWindowLevel;
|
||||
}
|
||||
NSMenu *associationMenu = [[NSMenu alloc] init];
|
||||
[associationMenu addItemWithTitle:NSLocalizedString(@"SELECT_AUTOTYPE_CANDIDATE", "") action:NULL keyEquivalent:@""];
|
||||
[associationMenu addItem:[NSMenuItem separatorItem]];
|
||||
[associationMenu setAutoenablesItems:NO];
|
||||
associationMenu.autoenablesItems = NO;
|
||||
for(MPAutotypeContext *context in candidates) {
|
||||
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:context.entry.title action:0 keyEquivalent:@""];
|
||||
[item setRepresentedObject:context];
|
||||
@@ -263,12 +266,12 @@ NSString *const kMPProcessIdentifierKey = @"kMPProcessIdentifierKey";
|
||||
|
||||
for(NSString *value in attributes) {
|
||||
NSMenuItem *valueItem = [[NSMenuItem alloc] initWithTitle:value action:NULL keyEquivalent:@""];
|
||||
[valueItem setIndentationLevel:1];
|
||||
[valueItem setEnabled:NO];
|
||||
valueItem.indentationLevel = 1;
|
||||
valueItem.enabled = NO;
|
||||
[associationMenu addItem:valueItem];
|
||||
}
|
||||
}
|
||||
[self.matchSelectionButton setMenu:associationMenu];
|
||||
self.matchSelectionButton.menu = associationMenu;
|
||||
[self.matchSelectionWindow makeKeyAndOrderFront:self];
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user