addGlobalMonitorForEventsMatchingMask不起作用 [英] addGlobalMonitorForEventsMatchingMask not working
问题描述
我在获取启用了辅助功能的应用程序(在开发案例中为XCode)来捕获全局keyDown事件时遇到了麻烦.我已经看到了很多类似下面的代码示例,但是在10.9.4上对我来说这不起作用.
I am having trouble with getting an assistive-enabled application (XCode in the development case) to capture global keyDown events. I've seen lots of code examples like the below, but this doesn't work for me on 10.9.4.
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
// 10.9+ only, see this url for compatibility:
// http://stackoverflow.com/questions/17693408/enable-access-for-assistive-devices-programmatically-on-10-9
BOOL checkAccessibility()
{
NSDictionary* opts = @{(__bridge id)kAXTrustedCheckOptionPrompt: @YES};
return AXIsProcessTrustedWithOptions((__bridge CFDictionaryRef)opts);
}
int main(int argc, const char * argv[])
{
@autoreleasepool {
if (checkAccessibility()) {
NSLog(@"Accessibility Enabled");
}
else {
NSLog(@"Accessibility Disabled");
}
NSLog(@"registering keydown mask");
[NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask
handler:^(NSEvent *event){
NSLog(@"keydown: %@", event.characters);
}];
NSLog(@"entering run loop.");
[[NSRunLoop currentRunLoop] run];
}
return 0;
}
收到的输出是:
2014-08-25 17:26:36.054 test[64725:303] Accessibility Enabled
2014-08-25 17:26:36.055 test[64725:303] registering keydown mask
2014-08-25 17:26:36.067 test[64725:303] entering run loop.
在这里,无论我按下哪个键或按下哪个应用程序具有焦点,都不会发生其他日志记录.
Once here, no other logging occurs, regardless of which keys I hit or what application has focus when I hit them.
FWIW,我正在尝试编写辅助应用程序,而不是键盘记录器或其他有害的东西.我看过这个问题的其他实例,但它们似乎处理以下问题:1)应用程序未启用辅助功能;或者2)未接收到某些需要CGEvents接收的特殊"命令键.我没有看到任何键,甚至没有看到简单的键(在我输入这篇文章的过程中一直在运行,并且没有记录任何内容). TIA!
FWIW, I'm trying to write an assistive application, not a key-logger or other evil thing. I've looked at the other instances of this question, but they seem to deal with either 1) the application not being assistive-enabled or 2) not receiving certain 'special' command keys that one would need CGEvents to receive. I am not seeing any keys, even simple ones (it's been running through my typing of this post and nothing was logged). TIA!
推荐答案
因此,多亏了Ken Thomases提出的上述问题,我才能够找到解决方法.关键的细节是我正在使用命令行应用程序模板(我不需要UI,因此我试图将事情减至最少).对我来说是新闻,但事后看来很明显,仅创建运行循环并不会创建事件循环.为了在命令行应用程序中复制事件循环的创建,必须使用典型可可应用程序的更多胆量.首先,您必须具有一个实现NSApplicationDelegate协议的类,该委托将是应用程序代码所在的位置,而main方法仅需执行以下操作:
So, thanks to Ken Thomases' question above, I was able to work out how to do this. The key detail is that I am using a command line application template (I don't have any need for a UI, so I was trying to keep things minimal). News to me, but obvious in hindsight, just creating a run loop doesn't create an event loop. In order to replicate the creation of an event loop within a command line application, more of the guts of a typical cocoa application have to be brought into play. First, you have to have a class implementing the NSApplicationDelegate protocol, and that delegate will be where the application code lives, leaving the main method to simply do the following:
#import <Foundation/Foundation.h>
#include "AppDelegate.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
AppDelegate *delegate = [[AppDelegate alloc] init];
NSApplication * application = [NSApplication sharedApplication];
[application setDelegate:delegate];
[NSApp run];
}
}
这是一个无笔尖,无菜单栏的应用程序,就像通常的命令行应用程序模板一样,但是由于有[NSApp run]
调用,它确实具有真正的事件循环.然后将我以前在上面的main方法中拥有的应用程序代码移到应用程序委托中:
This is a nib-less, menubar-less application, just like the usual command line application template, but it does have a true event loop, due to the [NSApp run]
call. Then the application code that I used to have in my main method above moved into the app delegate:
#import "AppDelegate.h"
@implementation AppDelegate
// 10.9+ only, see this url for compatibility:
// http://stackoverflow.com/questions/17693408/enable-access-for-assistive-devices-programmatically-on-10-9
BOOL checkAccessibility()
{
NSDictionary* opts = @{(__bridge id)kAXTrustedCheckOptionPrompt: @YES};
return AXIsProcessTrustedWithOptions((__bridge CFDictionaryRef)opts);
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
if (checkAccessibility()) {
NSLog(@"Accessibility Enabled");
}
else {
NSLog(@"Accessibility Disabled");
}
NSLog(@"registering keydown mask");
[NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask
handler:^(NSEvent *event){
NSLog(@"keydown: %@", event.characters);
}];
}
@end
为了完整起见和将来的读者,头文件看起来像这样:
And just for completeness sake and future readers, the header file looks like this:
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification;
@end
这篇关于addGlobalMonitorForEventsMatchingMask不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!