AppleScript triggered by user app activation (and deactivation)

I am relatively new to the Mac (since 2002) and recently upgraded from Jaguar to Tiger. I am now looking at using AppleScript to run a very simple terminal command but I would like it to happen automatically based on user activation of an app. For example, when iTerm is activated I would like automatic triggering of a script to toggle a setting via a (separate backgrounded) terminal command. And then when the app is deactivated, automatic triggering of the other half of the script (or another script) to toggle the setting back.

I have already been browsing around through this forum and googling the web and haven’t found any postings by someone else who has done this. I emailed FastScripts support and was told that, “FastScripts is aware of the current application changing, it only uses this information right now to change the list of scripts and keyboard shortcuts that are active for that particular app.” So I know theres a way to get a handle on activation of an app (and therefore deactivation, if not directly then through some notification that another app has activated). So can anyone here give me some guidance as to how to handle this? Perhaps even a rough script from which to start?

Thanks.

Just to clarify: By activate I mean when the app to be modified (iTerm in the example) becomes the foremost window, whether by initial launch or navigating to an existing window using any means (mouse or keyboard). By deactivate I mean when another app has been brought to the front or the modified app (iTerm) is closed.

http://osaxen.com/files/uiactions1.1.1.html

Something as:

--> pseudo-code
attach script blah to application blah for notification "AXApplicationActivated"

The cheap’n’dirty solution would be saving this as stay-open application:

global lastone

set lastone to missing value


on idle
	set currentone to path to frontmost application as text
	if currentone ends with "Finder.app:" then
		if currentone is not lastone then
			tell application currentone to display dialog "OK" giving up after 2
		end if
	end if
	
	set lastone to currentone
	return 0.2
end idle

OK, jj, I think I see what the first script is doing. Here is the script I need to run when iTerm activates:

do shell script "sysctl -w dc.config=0"

It seems that attaching this in the way you described will accomplish half of what I’m trying to do.

Then when iTerm deactivates:

do shell script "sysctl -w dc.config=65536"

Not sure how to get this half done (or what was the intention of your second script). You may have to explain it a bit or point me to a reference link that I can get up to speed on all the syntax you used there.

Thanks for the help.

If you use UI Actions, the job is done, as you can attach your script to the de-activated event (whatever is called).

About the script I posted, if you save it as stay-open application, the “idle” handler will be run every “x” seconds (in this example, 0.2 seconds, as stated in the return statement). It will simply use some if/end-if to check the current frontmost application against the previous frontmost application. Here is a slighly modified version, which will also react upon selected app deactivation (in this example, the Finder). It’s not very smart, but may work for simple tasks (otherwise, I recommend UI Actions):

property targetApp : "Finder.app:"

global previousFrontmostApp

set previousFrontmostApp to missing value


on idle
	set currentFrontmostApp to path to frontmost application as text
	if currentFrontmostApp ends with targetApp then
		if currentFrontmostApp is not previousFrontmostApp then --> activated!
			tell application currentFrontmostApp to display dialog targetApp & " activated!" giving up after 2
		end if
	else if previousFrontmostApp ends with targetApp then --> deactivated!
		tell application currentFrontmostApp to display dialog targetApp & " deactivated!" giving up after 2
	end if
	
	--> update value of previousFrontmostApp
	set previousFrontmostApp to currentFrontmostApp
	
	--> run this "idle" handler every 0.2 seconds
	return 0.2
end idle

More about “idle” handlers in our FAQ:
http://bbs.applescript.net/viewtopic.php?pid=46903
http://bbs.applescript.net/viewtopic.php?pid=46883

Ok this is what I have saved as a stay open app:

property targetApp : "iTerm.app:"

global previousFrontmostApp

set previousFrontmostApp to missing value


on idle
	set currentFrontmostApp to path to frontmost application as text
	if currentFrontmostApp ends with targetApp then
		if currentFrontmostApp is not previousFrontmostApp then --> activated!
			do shell script "sysctl -w dc.config=0"
		end if
	else if previousFrontmostApp ends with targetApp then --> deactivated!
		do shell script "sysctl -w dc.config=65536"
	end if
	
	--> update value of previousFrontmostApp
	set previousFrontmostApp to currentFrontmostApp
	
	--> run this "idle" handler every 0.2 seconds
	return 0.2
end idle

I’m reading the links you posted about idle handlers. Please let me know if you think of anything else that may help.

Thanks.

The applet/script seems to work OK so far. But a I have discovered couple things that bear discussion and maybe tweaking.

Applying the same sort of shell commands to other applications as they activate/deactivate: I believe this needs to be applied to my VNC client (Chicken of the VNC) as was done for iTerm. But I’m thinking that it must be done in a single script, rather than one for each app, in order to prevent conflicts.

Fast User Switching (FUS): I think the script becomes a hindrance when switching users. I think the way it would work best is if the script only runs the idle handler whenever my user is logged in. And if I could run the script (or a variation of the script) for the another user that has logged in as well (via FUS) with similar behavior. Then only one idle handler would run at a time and they would not conflict.

Any suggestions to address these?

Thanks again.

Something else I just noticed: The script takes up a steady 6.5% CPU. Seems a little high for something so minor. I think perhaps it would be better to change from this idle handler script running every 0.2 sec to a script that is triggered by the window manager. I mean there has to be something coming from the system to the graphics engine or else how does the system know which window to bring to the front? So basically I would like to see the script run once every time a new window comes to the front.

jj? Anybody else?

Yes, what you say is done by PreFab’s UI Actions :wink:

(see link above)