Search code examples
javascriptmacosapplescriptautomator

Is it possible to send a key code to an application that is not in front?


I'm writing a simple Automator script in Javascript.

I want to send a key-code(or key-storke) to an OS X application that is not in front.

Basically, I want to run this code and do my things while the script opens a certain application, write text, and hit enter - all of this without bothering my other work.

I want something like this: Application("System Events").processes['someApp'].windows[0].textFields[0].keyCode(76);

In Script Dictionary, there is keyCode method under Processes Suite. The above code, however, throws an error that follows: execution error: Error on line 16: Error: Named parameters must be passed as an object. (-2700)

I understand that the following code works fine, but it require the application to be running in front: // KeyCode 76 => "Enter" Application("System Events").keyCode(76);

UPDATE: I'm trying to search something on iTunes(Apple Music). Is this possible without bringing iTunes app upfront?


Solution

  • It's possible to write text in application that is not in front with the help of the GUI Scripting (accessibility), but :

    • You need to know what UI elements are in the window of your specific application, and to know the attributes and properties of the specific element.
    • You need to add your script in the System Preferences --> Security & Privacy --> Accessibility.

    Here's a sample script (tested on macOS Sierra) to write some text at the position of the cursor in the front document of the "TextEdit" application.

    Application("System Events").processes['TextEdit'].windows[0].scrollAreas[0].textAreas[0].attributes["AXSelectedText"].value = "some text" + "\r" // r is the return KEY
    

    Update

    To send some key code to a background application, you can use the CGEventPostToPid() method of the Carbon framework.

    Here's the script to search some text in iTunes (Works on my computer, macOS Sierra and iTunes Version 10.6.2).

    ObjC.import('Carbon')
    iPid = Application("System Events").processes['iTunes'].unixId()
    searchField = Application("System Events").processes['iTunes'].windows[0].textFields[0]
    searchField.buttons[0].actions['AXPress'].perform()
    delay(0.1) // increase it, if no search 
    searchField.focused = true
    delay(0.3) // increase it, if no search 
    searchField.value = "world" // the searching text
    searchField.actions["AXConfirm"].perform()
    delay(0.1) // increase it, if no search 
    
    // ** carbon methods to send the enter key to a background application ***
    enterDown = $.CGEventCreateKeyboardEvent($(), 76, true);
    enterUp = $.CGEventCreateKeyboardEvent($(), 76, false);
    $.CGEventPostToPid(iPid, enterDown);
    delay(0.1)
    $.CGEventPostToPid(iPid, enterUp);