Search code examples
applescriptcocoa-scripting

Cocoa Scripting: How do I use AppleScript handlers (events)?


Adding scriptability to my Mac app, I wonder if I can invoke handlers on the script's end from my app. If so, how does that work?

As I understand it, handlers are like functions (as in "on run") that can be called by events coming from outside of the script's own code. And the Sdef file understands the event tag, seeing that I can enter events using the Sdef Editor. But I cannot find any documentation on this in the Cocoa Scripting Guide.

My app records the clipboard, so I wonder if I could let running scripts know that a new clipboard has been recorded so that the script can operate on it.

Now, instead of invoking separate (stand-alone) scripts that I locate and load and run for such an event, I would rather like it if the user could have a script run constantly that declares an event that my app then invokes. (Whether that's really a good idea should not be discussed here, I'm just using this as an example for understanding AppleScript events.)

Is that possible? If not, what are the event entries in the sdef meant for?

Update: Here's an intro on handlers in AppleScript: MacScripter: Getting Started with Handlers


Solution

  • The difficulty to implement AppleScript Event Handlers is that the application must have a permanent reference to the script.

    For example the scripts to handle event handlers in Finder, Messages, Mail must be registered in the target application to keep the reference to the script.

    When the script implements one of the provided event handlers, the target application creates an NSAppleEventDescriptor with

    initWithEventClass:kHandlerEventClass 
               eventID:kEventID
      targetDescriptor:kEventTargetDescriptor 
              returnID:kAutoGenerateReturnID // predefined constant in CarbonCore.h
         transactionID:kAnyTransactionID]; // predefined constant in CarbonCore.h
    

    including the sub-descriptors for the parameters, and send it via executeAppleEvent on the target script reference.

    • kEventID is the least 4 significant bits of the 8 char code in the sdef file ('EfgH').
    • kHandlerEventClass are the most 4 significant bits of the 8 char code in the sdef file ('abcD').
    • kEventTargetDescriptor is an NSAppleEventDescriptor representing the client or target application as return address .

    The event handler works similar to a command, here an very basic example

    <event name="did appear something" code="abcDEfgH" description="This handler is called when something appears.">
         <direct-parameter description="The names of the appeared something.">
            <type type="text" list="yes"/>
         </direct-parameter>
         <parameter name="with result" code="smTS" description="A record of some information about the names" type="something reply"/>
    </event>
    

    in AppleScript the handler is implemented

    on did appear something theNames with result theResult
    
    • theNames is a list of text
    • theResult is a custom record type something reply