Ensure window focus at launch

I’ve been struggling to get an enhanced window to be focused after launching the script from Alfred or Keyboard Maestro. I tried executing it from Alfred’s main thread as a NSAppleScript and through the command line as /usr/bin/osascript var_viewer.scptd but regardless, when the window launches it is not focused. Below is a example (note how i have to click the window for it to become active):

DTPwindow-focus

This issue does not happen when executed in Script Debugger, so I assume the issue is related to how the current application is osascript (not being an application which can be frontmost) when executed from the command line, Alfred, or Keyboard Maestro. The whole script is below, any input would be great, thanks!

--
--	Created by: Kevin Funderburg
--	Created on: 9/11/20
--
--	Copyright © 2020 funderburg, All Rights Reserved
--

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions
use script "Dialog Toolkit Plus"
property ICON_KM : "/System/Volumes/Data/Applications/Keyboard Maestro.app/Contents/Resources/Variable.icns"

on run argv
	
	if class of argv = script then -- for testing
		set argv to {"_path", "System/Volumes/Data/Applications/Keyboard Maestro.app/Contents/Resources/Variable.icn"}
	end if
	set {_name, val} to argv
	
	set {width, height} to screensize()
	set maxFieldHeight to height * 0.75
	set lineCount to count of paragraphs of val
	set fieldHeight to 15 * lineCount
	if fieldHeight > maxFieldHeight then set fieldHeight to maxFieldHeight
	set maxWidth to 550
	set minWidth to 400
	set accWidth to getLongestLine(val)
	set accWidth to (accWidth / 1.5) * 10
	if accWidth > maxWidth then
		set accWidth to maxWidth
	else if accWidth < minWidth then
		set accWidth to minWidth
	end if
	set accViewWidth to accWidth
	
	set {theButtons, minWidth} to ¬
		create buttons {"Cancel", "Delete", "OK"} ¬
			button keys {"", "d", ""} ¬
			default button 3 ¬
			cancel button 1
	if minWidth > accViewWidth then set accViewWidth to minWidth -- make sure buttons fit
	if lineCount > 1 then
		set {theField, theTop} to ¬
			create field (val) ¬
				placeholder text ("Enter your text here") ¬
				bottom 0 ¬
				field width accViewWidth ¬
				extra height fieldHeight ¬
				with accepts linebreak and tab
	else
		set {theField, theTop} to ¬
			create field (val) ¬
				placeholder text ("Enter your text here") ¬
				bottom 0 ¬
				field width accViewWidth ¬
				extra height fieldHeight ¬
				without accepts linebreak and tab
	end if
	set {regLabel, theTop} to ¬
		create label ("OK:" & tab & tab & "Dismiss or set variable to new value" & return & ¬
			"Delete:" & tab & "Delete variable from Keyboard Maestro (⌘D)" & return & ¬
			"Cancel:" & tab & "⎋") ¬
			bottom theTop + 10 ¬
			max width accViewWidth ¬
			left inset 75 ¬
			control size regular size ¬
			aligns left aligned
	set {theRule, theTop} to ¬
		create rule (theTop + 12) ¬
			left inset 75 ¬
			rule width accViewWidth - 60
	set {boldLabel, theTop} to ¬
		create label ("View or edit the Keyboard Maestro variable here.") ¬
			bottom theTop + 10 ¬
			max width accViewWidth ¬
			left inset 75 ¬
			control size regular size ¬
			aligns left aligned ¬
			with bold type
	set {imgView, theTop} to ¬
		create image view (ICON_KM) ¬
			left inset 10 ¬
			bottom theTop - 50 ¬
			view width 50 ¬
			view height 50 ¬
			scale image scale proportionally ¬
			align image top left aligned
	set {buttonName, controlsResults} to ¬
		display enhanced window ("Keyboard Maestro Variable Viewer") ¬
			acc view width accViewWidth ¬
			acc view height theTop + 5 ¬
			acc view controls {theField, regLabel, theRule, boldLabel, imgView} ¬
			buttons theButtons ¬
			active field theField ¬
			initial position {} ¬
			with align cancel button
	
	if buttonName = "OK" then
		set newVal to item 1 of controlsResults
		if newVal ≠ val then
			tell application "Keyboard Maestro Engine" to setvariable _name to newVal
			display notification ("'" & _name & "' updated to " & newVal)
		end if
	end if
	
end run

on getLongestLine(txt)
	set max to 0
	repeat with p in paragraphs of txt
		if (count of characters of contents of p) > max then
			set max to count of characters of contents of p
		end if
	end repeat
	return max
end getLongestLine

on screensize()
	set theScreen to current application's NSScreen's mainScreen()
	set theFrame to theScreen's visibleFrame()
	set width to item 1 of item 2 of theFrame
	set height to item 2 of item 2 of theFrame
	return {width, height}
end screensize

Maybe you can add a activate me statement after the dialog display?

I used ( some assembly required ):

activate application runningApp
tell application “System Events” to set frontmost of process runningApp to true
display dialog "Sent " & countPics & " screen pictures to " & recipientAddress giving up after 4

Maybe I’m missing something is “runningApp” a special reference in AppleScript or a generic placeholder which needs to be replaced with an appropriate app. Here was the solution backed into for my specific DialogToolkit case using explorer
tell application “System Events”
tell its process “osascript”
set frontmost to true
end tell
end tell

but it still doesn’t work in the context of KM. It seems like the dialog call is blocking until it gets a response so the call to move to frontmost isn’t happening until after dialog has been processed. Am i missing something?

In that context “runningApp” would be a placeholder.

If your script is being run from within the applet, simply:

tell me to activate 

If your script is being run somewhere else, and you want to bring the Applet to the front then:

tell application "MyApp Name or Path" to activate

In the second command you may just be able to use the name of your app, but you may be asked to navigate to it. You could also provide the full path.

Ok, I understand you were answering the general case, i think this may be a specific issue with the Dialog Toolkit implementation. It seems that the display enhance window call is completely self contained. It doesn’t exist until the call and doesn’t return until user responds to the dialog, so there isn’t a way to activate it from within the calling script. Maybe it can be injected into the Toolkit scripting library. I’ll have to dig through that. Thanks for responding.

1 Like

Did you manage to solve the problem?
I currently try to solve the same :)…