6

I'm trying to create an OSX application which would be a replica of On Screen keyboard. Is it possible to insert some text into the cursor position of another active application? Thanks in advance!

Selvin
  • 12,333
  • 17
  • 59
  • 80
  • 1
    FYI, just in case: The answer (whatever the details, sorry I don't know them offhand) is a *qualified* yes - as for example that is how assistive software works. *However* under the sandbox, and hence in the App Store, the general answer is most certainly no - typing into another app is potentially a serious security issue. Of course if your application won't be in the sandbox then its restrictions won't matter. – CRD Apr 29 '13 at 18:55
  • @CRD what do you mean by sandbox. Do you mean that if i submit the app to appstore it wont work? But as a apple developer i would be able to run this app in my system? Can you please elaborate..Thanks. – Selvin Apr 30 '13 at 09:01
  • 1
    the App Sandbox is a security system which limits what an app can do - what files it can access, whether it can make network connections, etc, etc. All iOS apps are sandboxed, for OS X it is optional. However all apps to be sold in the Mac App Store must be sandboxed. Look up App Sandbox in the Apple docs for the details. – CRD Apr 30 '13 at 10:13

2 Answers2

10

It is possible. Accessibility enables to change content of other applications, but your app can't be sandboxed and thus not available via AppStore.

CFTypeRef focusedUI;
AXUIElementCopyAttributeValue(AXUIElementCreateSystemWide(), kAXFocusedUIElementAttribute, &focusedUI);

if (focusedUI) {
    CFTypeRef textValue, textRange;
    // get text content and range
    AXUIElementCopyAttributeValue(focusedUI, kAXValueAttribute, &textValue);
    AXUIElementCopyAttributeValue(focusedUI, kAXSelectedTextRangeAttribute, &textRange);

    NSRange range;
    AXValueGetValue(textRange, kAXValueCFRangeType, &range);
    // replace current range with new text
    NSString *newTextValue = [(__bridge NSString *)textValue stringByReplacingCharactersInRange:range withString:newText];
    AXUIElementSetAttributeValue(focusedUI, kAXValueAttribute, (__bridge CFStringRef)newTextValue);
    // set cursor to correct position
    range.length = 0;
    range.location += text.length;
    AXValueRef valueRef = AXValueCreate(kAXValueCFRangeType, (const void *)&range);
    AXUIElementSetAttributeValue(focusedUI, kAXSelectedTextRangeAttribute, valueRef);

    CFRelease(textValue);
    CFRelease(textRange);
    CFRelease(focusedUI);
}

This code does not check for errors and makes assumption that focused element is text area.

Miroslav Hrivik
  • 822
  • 13
  • 16
  • This way doesn't work on web based app :( e.g: Safari, Slack (Electron) or Skype (React-Native) – Tran Quan Dec 23 '20 at 21:11
  • i'm ending up here because i've reached the same solution but between the time i paste the next and the time i move the caret, the caret flickers and that makes the UX of my app pretty bad. haven't found any solution unfortunately. – godbout May 09 '21 at 18:29
2

Not sure if this helps, but in Applescript you can do something like

tell application "System Events"
    keystroke "Stuff here"
end tell

So maybe you can try call that within cocoa using NSApplescript or using NSTask and run

osascript -e 'tell application "System Events" to keystroke "Stuff here"'
TheAmateurProgrammer
  • 9,252
  • 8
  • 52
  • 71
  • 1
    This won't work on the Mac App Store either, so you'd best clarify this. – SevenBits Feb 26 '14 at 13:41
  • 1
    Adding onto the comment above: most people resort to turning off their app sandboxes. According to https://developer.apple.com/forums/thread/693312, Apple won't allow App Store distribution with it turned off. It may be possible to leave the sandbox on if you use your `info.plist`'s `com.apple.security.temporary-exception.apple-events` array key to grant security exceptions for different apps. I'm not sure though because I haven't tried it. – Xavier L. Apr 29 '23 at 19:07