1

I am simulating keystrokes in macOS, and sending them to the active application. I am doing it along the lines of https://stackoverflow.com/a/27487493/5600424 but in Swift 3. For example, to send an 'a':

let eventSource = CGEventSource(stateID: CGEventSourceStateID.hidSystemState)
let key: CGKeyCode = 0     // virtual key for 'a'
let eventDown = CGEvent(keyboardEventSource: eventSource, virtualKey: key, keyDown: true)
let eventUp = CGEvent(keyboardEventSource: eventSource, virtualKey: key, keyDown: false)
let location = CGEventTapLocation.cghidEventTap
eventDown.post(tap: location)
eventUp.post(tap: location)

This was working fine on OSX El Capitan (Swift 3, Xcode 8.0), but it stopped working after updating to macOs Sierra. The application itself still receives the keystroke when it's active, however when a different application is active the events seem lost. I have tried to figure out what is happening without success, and the documentation does not help. Any help would be appreciated, thanks!

Community
  • 1
  • 1
tin
  • 86
  • 1
  • 6
  • Have you tried posting to a different tap location, such as `CGEventTapLocation.cgSessionEventTap`? Or, if you're targeting a specific application, using `postToPSN()`? – Ken Thomases Sep 22 '16 at 21:19
  • Hi @Ken, I am not targeting a specific application, I'd like the active window of the foreground application to receive the events (the one the user is interacting with). It was working as I intended pre-sierra. I also tried `CGEventTapLocation.cgSessionEventTap`, but the behavior doesn't change: the events are ignored if I switch to another application. Maybe the correct way to do it is to track the foreground application with `NSWorkspace.shared().runningApplications.first(where: { $0.isActive })` and use `postToPSN()`? – tin Sep 22 '16 at 22:20
  • 1
    Well, it would be more proper to use `NSWorkspace.shared().frontmostApplication`. ;) You can certainly try that. It may also be that Sierra tightened up event posting security and you need to have assistive access like you would need for key event tapping. – Ken Thomases Sep 22 '16 at 22:46
  • Hi Ken, it turns out that the keystrokes were not sent at all because of a different problem. They still behave the same as before the upgrade, and there is no need to have assistive access. Thanks a lot for your help! – tin Sep 24 '16 at 17:07
  • Please don't include the answer in your question. You can post your own answer if you resolved your problem yourself. Thank you. – Eric Aya Sep 25 '16 at 12:11
  • Thanks Eric, I added the answer as you suggested. – tin Sep 25 '16 at 16:33

1 Answers1

1

The code quoted in the question works correctly, and its behavior has not changed when upgrading from El Capitan to Sierra, contrary to what claimed.

The keystrokes where not received by other applications because once the application was in the background, the function responsible for sending the keyboard events with the above code was not called anymore, for independent reasons.

tin
  • 86
  • 1
  • 6