How to detect keystrokes globally in Swift on macOS?
Asked Answered
V

2

13

Here is what I tried:

NSEvent.addGlobalMonitorForEvents(matching: [.keyDown]) { (event) in
    print(event.keyCode)
}

Unfortunately, it does not print anything.

And no, it's not a duplicate of this, that question is about modifier keys, my question is about keystrokes.

Viniculture answered 31/8, 2017 at 17:1 Comment(2)
Does this answer your question? How to listen to global hotkeys with Swift in a macOS app?Beady
For future readers, cause I spent all day trying to figure this out https://mcmap.net/q/905142/-how-to-get-keyboard-inputs-non-string-in-command-line-tool-application-in-swiftRogatory
H
21

Looks like the "duplicate" mark got removed, but so has the answer that I kludged into the comments section. So, for posterity:

The reason this doesn't work is because global monitors for .keyDown events require more permissions than some of the other event handlers, including the one that somebody thought this was a duplicate of. This is mainly because global .keyDown monitors can be used for nefarious purposes, such as keyloggers. So there are additional security measures in place to make sure we're legit:

1) Your app needs to be code-signed.

2) Your app needs to not have the App Sandbox enabled, and:

3) Your app needs to be registered in the Security and Privacy preference pane, under Accessibility.

The third one of these things has to be enabled by the user, but you can nudge them in that direction with this code:

let options: NSDictionary = [kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String : true]
let accessEnabled = AXIsProcessTrustedWithOptions(options)

if !accessEnabled {
    print("Access Not Enabled")
}

This will prompt the user, giving him/her the option to automatically open the appropriate preference pane where the user can allow your app to control the computer via the Accessibility API, which, assuming your app is signed and not sandboxed, will allow your global .keyDown monitor to work.

Halfandhalf answered 1/9, 2017 at 6:16 Comment(3)
I'm creating my first app, which is a kind of text expansion app. That means that it should be able to detect global keystrokes. Is the only way to test this functionality to sign up for a 100 euro developer license?Karilla
@Karilla To the best of my knowledge, yes, although you're going to want the license anyway because your app will be blocked by Gatekeeper otherwise.Halfandhalf
Condition #2 does not seem to apply, at least as of 10.15; that is to say, with App Sandbox enabled, my app indeed gets the events (so long as Accessibility permission has been granted).Es
P
1

if you only want global hotkey support all this is unnecessary (and not all random key or mouse events) you can do that easily with the hotkey API. look at e.g. PTHotkey :)

or a newer api .. seee also: How to implement shortcut key input in Mac Cocoa App?

Promethean answered 16/4, 2018 at 0:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.