From a2bc25e6719f8c2cff31c642b3786312a7672e68 Mon Sep 17 00:00:00 2001 From: michael starke Date: Fri, 27 Oct 2017 10:46:47 +0200 Subject: [PATCH] Enhanced autotype candidate selection selection window now uses a table instead of popup menu selection window will not activate MacPass and thus will not block view selection window displays evaluated placeholders (sans password) for better identification --- MacPass.xcodeproj/project.pbxproj | 20 ++------ MacPass/AutotypeCandidateSelectionView.xib | 51 ++++++++++--------- ...AutotypeCandidateSelectionViewController.h | 4 ++ ...AutotypeCandidateSelectionViewController.m | 48 ++++++++++++++--- MacPass/MPAutotypeDaemon.h | 5 +- MacPass/MPAutotypeDaemon.m | 38 +++----------- 6 files changed, 88 insertions(+), 78 deletions(-) diff --git a/MacPass.xcodeproj/project.pbxproj b/MacPass.xcodeproj/project.pbxproj index 691bcb43..c958d6ca 100644 --- a/MacPass.xcodeproj/project.pbxproj +++ b/MacPass.xcodeproj/project.pbxproj @@ -139,9 +139,8 @@ 4C6BC6601A36717E00BDDF3D /* MPDatabaseSearch.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C6BC65F1A36717E00BDDF3D /* MPDatabaseSearch.m */; }; 4C6D1D25178579570014C5A5 /* 48_FolderTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 4C6D1D24178579570014C5A5 /* 48_FolderTemplate.pdf */; }; 4C6DCC451FA2457900C8AD3F /* ContextBar.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C6DCC471FA2457900C8AD3F /* ContextBar.xib */; }; - 4C6DCC5B1FA24AC600C8AD3F /* AutotypeCandidateSelectionWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C6DCC5D1FA24AC600C8AD3F /* AutotypeCandidateSelectionWindow.xib */; }; 4C6DCC611FA24C2100C8AD3F /* MPAutotypeCandidateSelectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C6DCC5F1FA24C2100C8AD3F /* MPAutotypeCandidateSelectionViewController.m */; }; - 4C6DCC621FA24C2100C8AD3F /* AutotypeCandidateSelectionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C6DCC601FA24C2100C8AD3F /* AutotypeCandidateSelectionViewController.xib */; }; + 4C6DCC621FA24C2100C8AD3F /* AutotypeCandidateSelectionView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4C6DCC601FA24C2100C8AD3F /* AutotypeCandidateSelectionView.xib */; }; 4C6F228919A4A7F90012310C /* MPAutotypeClear.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C6F228819A4A7F90012310C /* MPAutotypeClear.m */; }; 4C6F228C19A4AA700012310C /* MPAutotypeDelay.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C6F228B19A4AA700012310C /* MPAutotypeDelay.m */; }; 4C701CBC178618A000581B88 /* 12_RemoteTemplate.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 4C701CBB178618A000581B88 /* 12_RemoteTemplate.pdf */; }; @@ -534,10 +533,9 @@ 4C6DCC571FA2458200C8AD3F /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/ContextBar.strings; sourceTree = ""; }; 4C6DCC591FA2458300C8AD3F /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/ContextBar.strings; sourceTree = ""; }; 4C6DCC5A1FA246ED00C8AD3F /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = de; path = de.lproj/Localizable.stringsdict; sourceTree = ""; }; - 4C6DCC5C1FA24AC600C8AD3F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/AutotypeCandidateSelectionWindow.xib; sourceTree = ""; }; 4C6DCC5E1FA24C2100C8AD3F /* MPAutotypeCandidateSelectionViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MPAutotypeCandidateSelectionViewController.h; sourceTree = ""; }; 4C6DCC5F1FA24C2100C8AD3F /* MPAutotypeCandidateSelectionViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MPAutotypeCandidateSelectionViewController.m; sourceTree = ""; }; - 4C6DCC601FA24C2100C8AD3F /* AutotypeCandidateSelectionViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AutotypeCandidateSelectionViewController.xib; sourceTree = ""; }; + 4C6DCC601FA24C2100C8AD3F /* AutotypeCandidateSelectionView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AutotypeCandidateSelectionView.xib; sourceTree = ""; }; 4C6F228719A4A7F90012310C /* MPAutotypeClear.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAutotypeClear.h; sourceTree = ""; }; 4C6F228819A4A7F90012310C /* MPAutotypeClear.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAutotypeClear.m; sourceTree = ""; }; 4C6F228A19A4AA700012310C /* MPAutotypeDelay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAutotypeDelay.h; sourceTree = ""; }; @@ -1498,7 +1496,7 @@ 4CA1827A1F96523600DD4A4A /* DuplicateEntryOptionsWindow.xib */, 4C6DCC5E1FA24C2100C8AD3F /* MPAutotypeCandidateSelectionViewController.h */, 4C6DCC5F1FA24C2100C8AD3F /* MPAutotypeCandidateSelectionViewController.m */, - 4C6DCC601FA24C2100C8AD3F /* AutotypeCandidateSelectionViewController.xib */, + 4C6DCC601FA24C2100C8AD3F /* AutotypeCandidateSelectionView.xib */, ); name = "Window Controller"; sourceTree = ""; @@ -1519,7 +1517,6 @@ 4CE8247216E2E99F00573141 /* Windows */ = { isa = PBXGroup; children = ( - 4C6DCC5D1FA24AC600C8AD3F /* AutotypeCandidateSelectionWindow.xib */, 4C1DDCDC1711ECEB00C98DA3 /* PasswordCreatorWindow.xib */, 4C7F8B6A1A10B68400CCB83D /* WelcomeWindow.xib */, ); @@ -1753,9 +1750,8 @@ 4C7ABA4A17BAEC6700FF5799 /* 17_CDRomTemplate.pdf in Resources */, 4C7ABA4B17BAEC6700FF5799 /* 19_EmailTemplate.pdf in Resources */, 4C3826C81AD04D8E007D7D67 /* 61_ServicesTemplate.pdf in Resources */, - 4C6DCC621FA24C2100C8AD3F /* AutotypeCandidateSelectionViewController.xib in Resources */, + 4C6DCC621FA24C2100C8AD3F /* AutotypeCandidateSelectionView.xib in Resources */, 4C0B038D18E36DA400B9F9C9 /* FixAutotypeWindow.xib in Resources */, - 4C6DCC5B1FA24AC600C8AD3F /* AutotypeCandidateSelectionWindow.xib in Resources */, 4C38267A1AD04CC6007D7D67 /* downloadTemplate.pdf in Resources */, 4C7ABA4C17BAEC6700FF5799 /* 20_MiscTemplate.pdf in Resources */, 4C7ABA4E17BAEC7000FF5799 /* addEntryTemplate.pdf in Resources */, @@ -1995,14 +1991,6 @@ name = ContextBar.xib; sourceTree = ""; }; - 4C6DCC5D1FA24AC600C8AD3F /* AutotypeCandidateSelectionWindow.xib */ = { - isa = PBXVariantGroup; - children = ( - 4C6DCC5C1FA24AC600C8AD3F /* Base */, - ); - name = AutotypeCandidateSelectionWindow.xib; - sourceTree = ""; - }; 4C7155DA1A10DB6D00979307 /* IconSelection.xib */ = { isa = PBXVariantGroup; children = ( diff --git a/MacPass/AutotypeCandidateSelectionView.xib b/MacPass/AutotypeCandidateSelectionView.xib index a48f3fb5..30d4eb0a 100644 --- a/MacPass/AutotypeCandidateSelectionView.xib +++ b/MacPass/AutotypeCandidateSelectionView.xib @@ -8,23 +8,24 @@ + + - - - + + - - + + - + - - + + @@ -47,21 +48,27 @@ - - - + + - - - - + + + + + + + + + + + @@ -85,13 +92,9 @@ - - - - - + @@ -119,10 +122,10 @@ Gw DQ - - - + + + @@ -139,7 +142,7 @@ DQ - + diff --git a/MacPass/MPAutotypeCandidateSelectionViewController.h b/MacPass/MPAutotypeCandidateSelectionViewController.h index fe7d035a..b44ec565 100644 --- a/MacPass/MPAutotypeCandidateSelectionViewController.h +++ b/MacPass/MPAutotypeCandidateSelectionViewController.h @@ -12,4 +12,8 @@ @property (copy) NSArray *candidates; +- (IBAction)selectAutotypeContext:(id)sender; +- (IBAction)cancelSelection:(id)sender; + + @end diff --git a/MacPass/MPAutotypeCandidateSelectionViewController.m b/MacPass/MPAutotypeCandidateSelectionViewController.m index d1be88a4..f85cb416 100644 --- a/MacPass/MPAutotypeCandidateSelectionViewController.m +++ b/MacPass/MPAutotypeCandidateSelectionViewController.m @@ -8,33 +8,69 @@ #import "MPAutotypeCandidateSelectionViewController.h" #import "MPAutotypeContext.h" +#import "MPAutotypeDaemon.h" + +#import "KPKNode+IconImage.h" #import @interface MPAutotypeCandidateSelectionViewController () +@property (weak) IBOutlet NSButton *selectAutotypeContextButton; +@property (weak) IBOutlet NSTableView *contextTableView; @end @implementation MPAutotypeCandidateSelectionViewController - (NSNibName)nibName { - return @"AutotypeCandidateSelectionViewController"; + return @"AutotypeCandidateSelectionView"; } +- (void)viewDidLoad { + [super viewDidLoad]; + self.selectAutotypeContextButton.enabled = NO; +} + +#pragma mark NSTableViewDataSource + - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { return self.candidates.count; } +#pragma mark NSTableViewDelegate + - (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { NSTableCellView *view = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self]; MPAutotypeContext *context = self.candidates[row]; - view.textField.stringValue = context.entry.title; - view.imageView.image = context.entry.icon.image; + NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@\n%@", context.entry.title, context.maskedEvaluatedCommand]]; + [string setAttributes:@{NSForegroundColorAttributeName: NSColor.disabledControlTextColor} range:NSMakeRange(context.entry.title.length + 1, context.maskedEvaluatedCommand.length)]; + view.textField.attributedStringValue = string; + view.imageView.image = context.entry.iconImage; return view; } -- (void)viewDidLoad { - [super viewDidLoad]; - // Do view setup here. + +- (void)tableViewSelectionDidChange:(NSNotification *)notification { + NSTableView *tableView = notification.object; + if(tableView != self.contextTableView) { + return; + } + self.selectAutotypeContextButton.enabled = (self.contextTableView.selectedRow != -1); } +#pragma mark Actions +- (void)selectAutotypeContext:(id)sender { + NSInteger selectedRow = self.contextTableView.selectedRow; + if(selectedRow >= 0 && selectedRow < self.candidates.count) { + [[MPAutotypeDaemon defaultDaemon] selectAutotypeCandiate:self.candidates[selectedRow]]; + } + else { + [self cancelSelection:sender]; // cancel since the selection was invalid! + } +} + +- (void)cancelSelection:(id)sender { + [[MPAutotypeDaemon defaultDaemon] cancelAutotypeCandidateSelection]; +} + + @end diff --git a/MacPass/MPAutotypeDaemon.h b/MacPass/MPAutotypeDaemon.h index 9948354c..dcce49a3 100644 --- a/MacPass/MPAutotypeDaemon.h +++ b/MacPass/MPAutotypeDaemon.h @@ -24,6 +24,7 @@ @class DDHotKey; @class KPKEntry; +@class MPAutotypeContext; /** * The autotype daemon is responsible for registering the global hotkey and to perform any autotype actions @@ -38,7 +39,7 @@ - (instancetype)init NS_UNAVAILABLE; - (void)performAutotypeForEntry:(KPKEntry *)entry; -- (IBAction)performAutotypeWithSelectedMatch:(id)sender; -- (IBAction)cancelAutotypeSelection:(id)sender; +- (void)selectAutotypeCandiate:(MPAutotypeContext *)context; +- (void)cancelAutotypeCandidateSelection; @end diff --git a/MacPass/MPAutotypeDaemon.m b/MacPass/MPAutotypeDaemon.m index 3997f800..6b19184a 100644 --- a/MacPass/MPAutotypeDaemon.m +++ b/MacPass/MPAutotypeDaemon.m @@ -140,16 +140,14 @@ static MPAutotypeDaemon *_sharedInstance; #pragma mark - #pragma mark Actions -- (void)performAutotypeWithSelectedMatch:(id)sender { - NSMenuItem *item = self.matchSelectionButton.selectedItem; - MPAutotypeContext *context = item.representedObject; +- (void)selectAutotypeCandiate:(MPAutotypeContext *)context { [self.matchSelectionWindow orderOut:self]; self.matchSelectionWindow = nil; [self _performAutotypeForContext:context]; } -- (void)cancelAutotypeSelection:(id)sender { - [self.matchSelectionWindow orderOut:sender]; +- (void)cancelAutotypeCandidateSelection { + [self.matchSelectionWindow orderOut:self]; self.matchSelectionWindow = nil; if(self.targetPID) { [self _orderApplicationToFront:self.targetPID]; @@ -299,38 +297,18 @@ static MPAutotypeDaemon *_sharedInstance; if(!self.matchSelectionWindow) { - //[[NSBundle mainBundle] loadNibNamed:@"AutotypeCandidateSelectionWindow" owner:self topLevelObjects:nil]; - self.matchSelectionWindow = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100) styleMask:NSWindowStyleMaskTitled backing:NSBackingStoreRetained defer:YES]; - //self.matchSelectionWindow.level = NSFloatingWindowLevel; + self.matchSelectionWindow = [[NSPanel alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100) + styleMask:NSWindowStyleMaskNonactivatingPanel|NSWindowStyleMaskTitled + backing:NSBackingStoreRetained + defer:YES]; + self.matchSelectionWindow.level = NSScreenSaverWindowLevel; MPAutotypeCandidateSelectionViewController *vc = [[MPAutotypeCandidateSelectionViewController alloc] init]; vc.candidates = candidates; self.matchSelectionWindow.contentViewController = vc; } - /*NSMenu *associationMenu = [[NSMenu alloc] init]; - [associationMenu addItemWithTitle:NSLocalizedString(@"SELECT_AUTOTYPE_CANDIDATE", "Menu item for selection a single match from multiple Autotype matches") action:NULL keyEquivalent:@""]; - [associationMenu addItem:[NSMenuItem separatorItem]]; - associationMenu.autoenablesItems = NO; - for(MPAutotypeContext *context in candidates) { - NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:context.entry.title action:0 keyEquivalent:@""]; - [item setRepresentedObject:context]; - [associationMenu addItem:item]; - NSArray *attributes = (context.entry.username.length > 0 ) - ? @[ context.entry.username, context.command ] - : @[ context.command ]; - - for(NSString *value in attributes) { - NSMenuItem *valueItem = [[NSMenuItem alloc] initWithTitle:value action:NULL keyEquivalent:@""]; - valueItem.indentationLevel = 1; - valueItem.enabled = NO; - [associationMenu addItem:valueItem]; - } - } - self.matchSelectionButton.menu = associationMenu; - */ [self.matchSelectionWindow center]; [self.matchSelectionWindow makeKeyAndOrderFront:self]; - [NSApp activateIgnoringOtherApps:YES]; } #pragma mark -