From 0c122364014039cd62574653831a1fd061c755b7 Mon Sep 17 00:00:00 2001 From: Michael Starke Date: Mon, 1 Jul 2019 14:40:10 +0200 Subject: [PATCH 1/4] Use naive polling to check if requested application is already active --- MacPass/MPAutotypeDaemon.m | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/MacPass/MPAutotypeDaemon.m b/MacPass/MPAutotypeDaemon.m index 8f84b017..4c277228 100644 --- a/MacPass/MPAutotypeDaemon.m +++ b/MacPass/MPAutotypeDaemon.m @@ -319,11 +319,7 @@ static MPAutotypeDaemon *_sharedInstance; return; // No context to work with } - if([self _orderApplicationToFront:self.targetPID]) { - /* Sleep a bit after the app was activated */ - /* TODO - we might be able to get a notification to check if the app actually was activated instead of guessing a waiting time */ - usleep(1 * NSEC_PER_MSEC); - } + [self _orderApplicationToFront:self.targetPID]; useconds_t globalDelay = 0; for(MPAutotypeCommand *command in [MPAutotypeCommand commandsForContext:context]) { @@ -442,15 +438,21 @@ static MPAutotypeDaemon *_sharedInstance; #pragma mark - #pragma mark Application information -- (BOOL)_orderApplicationToFront:(pid_t)processIdentifier { - NSRunningApplication *runingApplication = [NSRunningApplication runningApplicationWithProcessIdentifier:processIdentifier]; - NSRunningApplication *frontApplication = NSWorkspace.sharedWorkspace.frontmostApplication; - if(frontApplication.processIdentifier == processIdentifier) { - return NO; +- (void)_orderApplicationToFront:(pid_t)processIdentifier { + NSUInteger maxiumumWaitTime = 10; //ms + NSUInteger waitTime = 0; + while(waitTime < maxiumumWaitTime) { + NSRunningApplication *runingApplication = [NSRunningApplication runningApplicationWithProcessIdentifier:processIdentifier]; + NSRunningApplication *frontApplication = NSWorkspace.sharedWorkspace.frontmostApplication; + if(frontApplication.processIdentifier == processIdentifier) { + return; + } + [runingApplication activateWithOptions:NSApplicationActivateIgnoringOtherApps]; + usleep(1 * NSEC_PER_MSEC); + waitTime += 1; } - [runingApplication activateWithOptions:NSApplicationActivateIgnoringOtherApps]; - return YES; } + - (void)_updateTargetInformationForFrontMostApplication { [self _updateTargeInformationForApplication:NSWorkspace.sharedWorkspace.frontmostApplication]; } From ddb0f92dcee9eb1f56b1fc83f64457a80455891c Mon Sep 17 00:00:00 2001 From: Michael Starke Date: Mon, 1 Jul 2019 16:53:05 +0200 Subject: [PATCH 2/4] Using a notification based aproach to ensure the desired target application is activated before performing any autotype commands --- MacPass/MPAutotypeDaemon.m | 44 +++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/MacPass/MPAutotypeDaemon.m b/MacPass/MPAutotypeDaemon.m index 4c277228..b7fafb47 100644 --- a/MacPass/MPAutotypeDaemon.m +++ b/MacPass/MPAutotypeDaemon.m @@ -56,7 +56,7 @@ NSString *const kMPProcessIdentifierKey = @"kMPProcessIdentifierKey"; @property (copy) NSString *targetWindowTitle; // The title of the window that we are targeting @property (strong) NSRunningApplication *previousApplication; // The application that was active before we got invoked @property (assign) NSTimeInterval userActionRequested; - +@property (strong) id applicationActivationObserver; @end @implementation MPAutotypeDaemon @@ -108,6 +108,9 @@ static MPAutotypeDaemon *_sharedInstance; - (void)dealloc { [NSNotificationCenter.defaultCenter removeObserver:self]; [NSWorkspace.sharedWorkspace.notificationCenter removeObserver:self]; + if(self.applicationActivationObserver) { + [NSWorkspace.sharedWorkspace.notificationCenter removeObserver:self.applicationActivationObserver name:NSWorkspaceDidActivateApplicationNotification object:nil]; + } [self unbind:NSStringFromSelector(@selector(enabled))]; [self unbind:NSStringFromSelector(@selector(hotKeyData))]; } @@ -214,7 +217,7 @@ static MPAutotypeDaemon *_sharedInstance; [self.matchSelectionWindow orderOut:self]; self.matchSelectionWindow = nil; if(self.targetPID) { - [self _orderApplicationToFront:self.targetPID]; + [self _orderApplicationToFront:self.targetPID forContext:nil]; } } @@ -319,7 +322,9 @@ static MPAutotypeDaemon *_sharedInstance; return; // No context to work with } - [self _orderApplicationToFront:self.targetPID]; + if(NO == [self _orderApplicationToFront:self.targetPID forContext:(MPAutotypeContext *)context]) { + return; // We will get called back when the application is in front - hopfully + } useconds_t globalDelay = 0; for(MPAutotypeCommand *command in [MPAutotypeCommand commandsForContext:context]) { @@ -438,19 +443,28 @@ static MPAutotypeDaemon *_sharedInstance; #pragma mark - #pragma mark Application information -- (void)_orderApplicationToFront:(pid_t)processIdentifier { - NSUInteger maxiumumWaitTime = 10; //ms - NSUInteger waitTime = 0; - while(waitTime < maxiumumWaitTime) { - NSRunningApplication *runingApplication = [NSRunningApplication runningApplicationWithProcessIdentifier:processIdentifier]; - NSRunningApplication *frontApplication = NSWorkspace.sharedWorkspace.frontmostApplication; - if(frontApplication.processIdentifier == processIdentifier) { - return; - } - [runingApplication activateWithOptions:NSApplicationActivateIgnoringOtherApps]; - usleep(1 * NSEC_PER_MSEC); - waitTime += 1; +- (BOOL)_orderApplicationToFront:(pid_t)processIdentifier forContext:(MPAutotypeContext *)context { + NSRunningApplication *runingApplication = [NSRunningApplication runningApplicationWithProcessIdentifier:processIdentifier]; + NSRunningApplication *frontApplication = NSWorkspace.sharedWorkspace.frontmostApplication; + if(frontApplication.processIdentifier == processIdentifier) { + return YES; } + + /* cleanup before to make sure everything is top notch */ + if(self.applicationActivationObserver) { + [NSWorkspace.sharedWorkspace.notificationCenter removeObserver:self.applicationActivationObserver name:NSWorkspaceDidActivateApplicationNotification object:nil]; + self.applicationActivationObserver = nil; + } + + self.applicationActivationObserver = [NSWorkspace.sharedWorkspace.notificationCenter addObserverForName:NSWorkspaceDidActivateApplicationNotification object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) { + if(self.applicationActivationObserver) { + [NSWorkspace.sharedWorkspace.notificationCenter removeObserver:self.applicationActivationObserver name:NSWorkspaceDidActivateApplicationNotification object:nil]; + } + [self _performAutotypeForContext:context]; + }]; + + [runingApplication activateWithOptions:NSApplicationActivateIgnoringOtherApps]; + return NO; } - (void)_updateTargetInformationForFrontMostApplication { From 3cab0ea4dd52b14a48966eec0aada7fbe62df73a Mon Sep 17 00:00:00 2001 From: Michael Starke Date: Wed, 3 Jul 2019 11:02:10 +0200 Subject: [PATCH 3/4] Fixed versioning script to correctly work with more complex branches --- MacPass.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MacPass.xcodeproj/project.pbxproj b/MacPass.xcodeproj/project.pbxproj index 8ff06f6e..d34258e6 100644 --- a/MacPass.xcodeproj/project.pbxproj +++ b/MacPass.xcodeproj/project.pbxproj @@ -1963,7 +1963,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "git=`sh /etc/profile; which git`\nbranch_name=`$git symbolic-ref HEAD | sed -e 's,.*/\\\\(.*\\\\),\\\\1,'`\ngit_count=`$git rev-list $branch_name |wc -l | sed 's/^ *//;s/ *$//'`\nsimple_branch_name=`$git rev-parse --abbrev-ref HEAD`\n\nbuild_number=\"${git_count}0\"\nif [ $CONFIGURATION != \"Release\" ]; then\nbuild_number+=\"-$simple_branch_name\"\nfi\nif [ \"$CI\" = \"true\" ]; then\nbuild_date=`date +\"%Y%m%d%H%m%S\"`\nbuild_number=\"$build_date-continuous\"\nfi\n\nplist=\"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}\"\ndsym_plist=\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Info.plist\"\n\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $build_number\" \"$plist\"\nif [ -f \"$DSYM_INFO_PLIST\" ] ; then\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $build_number\" \"$dsym_plist\"\nfi\n"; + shellScript = "git=`sh /etc/profile; which git`\n#branch_name=`$git symbolic-ref HEAD | sed -e 's,refs/heads/\\\\(.*\\\\),\\\\1,'`\nbranch_name=`$git rev-parse --abbrev-ref HEAD`\n#simple_branch_name=`$git rev-parse --abbrev-ref HEAD`\ngit_count=`$git rev-list $branch_name |wc -l | sed 's/^ *//;s/ *$//'`\n\nbuild_number=\"${git_count}0\"\nif [ $CONFIGURATION != \"Release\" ]; then\nbuild_number+=\"-$branch_name\"\nfi\nif [ \"$CI\" = \"true\" ]; then\nbuild_date=`date +\"%Y%m%d%H%m%S\"`\nbuild_number=\"$build_date-continuous\"\nfi\n\nplist=\"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}\"\ndsym_plist=\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Info.plist\"\n\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $build_number\" \"$plist\"\nif [ -f \"$DSYM_INFO_PLIST\" ] ; then\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $build_number\" \"$dsym_plist\"\nfi\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ From 077a5851cfb05dc1585d7f87fc07ab935b4bf767 Mon Sep 17 00:00:00 2001 From: Michael Starke Date: Wed, 3 Jul 2019 11:14:42 +0200 Subject: [PATCH 4/4] append branch name if we're not on master --- MacPass.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MacPass.xcodeproj/project.pbxproj b/MacPass.xcodeproj/project.pbxproj index d34258e6..37da5583 100644 --- a/MacPass.xcodeproj/project.pbxproj +++ b/MacPass.xcodeproj/project.pbxproj @@ -1963,7 +1963,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "git=`sh /etc/profile; which git`\n#branch_name=`$git symbolic-ref HEAD | sed -e 's,refs/heads/\\\\(.*\\\\),\\\\1,'`\nbranch_name=`$git rev-parse --abbrev-ref HEAD`\n#simple_branch_name=`$git rev-parse --abbrev-ref HEAD`\ngit_count=`$git rev-list $branch_name |wc -l | sed 's/^ *//;s/ *$//'`\n\nbuild_number=\"${git_count}0\"\nif [ $CONFIGURATION != \"Release\" ]; then\nbuild_number+=\"-$branch_name\"\nfi\nif [ \"$CI\" = \"true\" ]; then\nbuild_date=`date +\"%Y%m%d%H%m%S\"`\nbuild_number=\"$build_date-continuous\"\nfi\n\nplist=\"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}\"\ndsym_plist=\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Info.plist\"\n\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $build_number\" \"$plist\"\nif [ -f \"$DSYM_INFO_PLIST\" ] ; then\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $build_number\" \"$dsym_plist\"\nfi\n"; + shellScript = "git=`sh /etc/profile; which git`\n#branch_name=`$git symbolic-ref HEAD | sed -e 's,refs/heads/\\\\(.*\\\\),\\\\1,'`\nbranch_name=`$git rev-parse --abbrev-ref HEAD`\n#simple_branch_name=`$git rev-parse --abbrev-ref HEAD`\ngit_count=`$git rev-list $branch_name |wc -l | sed 's/^ *//;s/ *$//'`\n\nbuild_number=\"${git_count}0\"\nif [ $CONFIGURATION != \"Release\" ] || [ $branch_name != \"master\" ]; then\nbuild_number+=\"-$branch_name\"\nfi\nif [ \"$CI\" = \"true\" ]; then\nbuild_date=`date +\"%Y%m%d%H%m%S\"`\nbuild_number=\"$build_date-continuous\"\nfi\n\nplist=\"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}\"\ndsym_plist=\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Info.plist\"\n\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $build_number\" \"$plist\"\nif [ -f \"$DSYM_INFO_PLIST\" ] ; then\n/usr/libexec/PlistBuddy -c \"Set :CFBundleVersion $build_number\" \"$dsym_plist\"\nfi\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */