Search code examples
cocoaaccessibilityuielement

How can I send an NSString to the currently focused UIElement of another application?


I have a menubar application without a dock icon or global menu, it's just a StatusItem and a Window.

I've got it wired up to a hotkey which activates the window and upon deactivating the window I am able to send focus back to the previously active application.

How can I send an NSString to the active textarea in the other application, as if the user had typed it directly?

I think it might be possible using accessibility features. I'd like to avoid using AppleScript if at all possible.


Solution

  • I ended up using the pasteboard and CGEventCreateKeyboardEvent() to mimic the [cmd+v] keyboard shortcut for pasting.

    Before activating my window, I record the previous application:

    _previousApplication = [[notification userInfo] objectForKey:NSWorkspaceApplicationKey];
    

    After I dismiss my window, I activate the previous application:

    [_previousApplication activateWithOptions:NSApplicationActivateIgnoringOtherApps];
    

    Then paste the NSString:

    #define KEY_CODE_v ((CGKeyCode)9)
    
    void DCPostCommandAndKey(CGKeyCode key) {
        CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState);
    
        CGEventRef keyDown = CGEventCreateKeyboardEvent(source, key, TRUE);
        CGEventSetFlags(keyDown, kCGEventFlagMaskCommand);
        CGEventRef keyUp = CGEventCreateKeyboardEvent(source, key, FALSE);
    
        CGEventPost(kCGAnnotatedSessionEventTap, keyDown);
        CGEventPost(kCGAnnotatedSessionEventTap, keyUp);
    
        CFRelease(keyUp);
        CFRelease(keyDown);
        CFRelease(source);
    }
    
    DCPostCommandAndKey(KEY_CODE_v);