Adding a global monitor with NSEventMaskKeyDown mask does not trigger

别来无恙 提交于 2021-02-07 04:31:19

问题


I'm working on a MacOS menu bar app which needs to track some global shortcuts in order to facilitate adjusting display brightness on external monitors. However, I cannot get it to fire a handler on any keyboard related events (mouse events work just fine).

I'm checking Accessibility with the following code

NSDictionary *options = @{CFBridgingRelease(kAXTrustedCheckOptionPrompt): @YES};
BOOL accessibilityEnabled = AXIsProcessTrustedWithOptions((CFDictionaryRef)options);

Then, I'm adding a global event monitor using:

self.eventMonitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSEventMaskKeyDown handler:^(NSEvent * event) {
    NSLog(@"Some event");
}];

If I switch NSEventMaskKeyDown to NSEventMaskMouseMove or something else mouse related, everything works fine. If I try NSEventMaskAny, nothing triggers again (which seems strange, as it should trigger on mouse still).


回答1:


The fact that NSEventMaskMouseMove works but NSEventMaskKeyDown doesn't is a clear sign that your app currently does not fullfill all requirements needed for tracking key events. NSEventMaskMouseMove is not considered as an event that needs special security protection and even works when AXIsProcessTrustedWithOptions returns false.

Key events require more permissions as mentioned by Charles Srstka in this answer:

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.

You need to enable code-signing in the General pane of your app target. Make sure that both "Team" and "Signing Certificate" are set:

You also have to disable the "App Sandbox" in the Capabilities pane:

Please note, that in order the meet the third requirement you als need to add Xcode itself to the Accessibility pane. Otherwise you want be able to debug your event monitoring.

Two more tips regarding key events:

  • Global monitoring only report events that occur in other apps. To monitor events in your own apps you need to use addLocalMonitorForEventsMatchingMask or the implementations from the Cocoa Event Handling Guide.
  • Key events sent to secure text field are masked, as mentioned by Jeff in this answer:

Key events sent to NSSecureTextField (or NSSecureTextFieldCell) are masked so that no event monitor can intercept or read them. This is a security feature to prevent applications from stealing passwords as they're typed, and there's no API to get around it.

A note about AppStore-compatible global shortcuts: It's clear that you can't upload an app to the AppStore that has its sandbox disabled. If you plan to distribute your app via the Mac AppStore (MAS) you have to use a different API. This thread mentions a bunch of solutions that are MAS-friendly. They use the RegisterEventHotKey API from the old Carbon days. Apple promised to not reject apps that use it.



来源:https://stackoverflow.com/questions/49716420/adding-a-global-monitor-with-nseventmaskkeydown-mask-does-not-trigger

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!