Click handler in Apple Script

applescriptbash

I created a standalone macOS app using Script Editor. Upon starting, the app executes a bash script and upon quitting, the app executes another bash script. The code looks like this

do shell script "complete path to start script"
on quit 
     do shell script "complete path to quit script"
     continue quit
end quit 

When I open the app it does what it is supposed to do and the app resides in the dock until it is closed. I would like the finder to open a specific folder when I click on the app symbol in the dock. Is there a way to do this?

Best Answer

Getting your application to respond specifically to a user clicking on its dock icon is difficult. A simpler task is to get your application to respond to acquiring focus where it previously belonged to another application, i.e. whenever your application is brought into the foreground, which clicking on the dock icon will do.

I've heavily commented the script below to walk you through what's relevant. Anything I've left uncommented or haven't specifically made reference to in the comments should be left alone and where it is, unless you're confident you know what you're doing.

Obviously, this won't do a lot if it's simply run from within Script Editor, so incorporate this into your application's AppleScript code (or, rather, incorporate your application's AppleScript code into this), save it, and run the applet. If you don't make any edits to it whatsoever, then when saved as an applet, you'll see a notification appear every 10 seconds telling you the application is "idling..."; and a dialog box will pop-up whenever the application is brought into focus informing you that it "Acquired focus.".

-----------------------------------------------------------|
on run
    _init()

    # Your startup code goes here, which will
    # execute once when your application runs
    # e.g.
    #   do shell script "/path/to/start-script.sh"
end run

on idle
    # Any code you need to run repeatedly can
    # go here.  Otherwise, you can delete this
    # entire handler

    # The following line is test code:
    display notification "idling..."

    # The return value is how often (in seconds)
    # this handler will be called
    return 10
end idle

on activate
    # Insert code you want to execute whenever
    # your application receives focus, e.g.
    # 
    #   tell application "System Events" to ¬
    #       open folder "~/Path/To/Folder/"

    # The following line is test code:
    display dialog "Focus acquired."
end activate

on quit
    global |@|
    |@|'s removeObserver:me

    # Any other clean-up code that needs to
    # execute just before your application
    # exits should go here, e.g.
    #   do shell script "/path/to/quit-script.sh"

    continue quit
end quit
-----------------------------------------------------------|
# PRIVATE HANDLERS:
use framework "Foundation"
use framework "AppKit"
use scripting additions

property |@| : a reference to my NSWorkspace's ¬
    sharedWorkspace's notificationCenter

on _init()
    "NSWorkspaceDidActivateApplicationNotification"
    |@|'s addObserver:me selector:("_notify:") ¬
        |name|:result object:(missing value)

    idle
end _init

to _notify:notification
    local notification
    if my id = the notification's userInfo()'s ¬
        NSWorkspaceApplicationKey's ¬
        bundleIdentifier() as text ¬
        then activate me
end _notify:
-----------------------------------------------------------|