应用程序随机停止接收按键(CGEventTaps)
所以,我浪费了很多时间来创建这个非常酷的键盘宏应用程序。它工作得很好,唯一的问题是几分钟后,它就停止工作了。当我按下某个键时,它不再被调用。
我没能锁定它,但它总是至少需要 30 秒才能发生。通常几分钟内不会发生。到时候我已经拦截并发出了很多事件。发生这种情况时应用程序仍在运行。
的示例
-(void)listen {
CFMachPortRef downEventTap = CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionDefault,CGEventMaskBit(kCGEventKeyDown),&onKeyDown,self);
downSourceRef = CFMachPortCreateRunLoopSource(NULL, downEventTap, 0);
CFRelease(downEventTap);
CFRunLoopAddSource(CFRunLoopGetCurrent(), downSourceRef, kCFRunLoopDefaultMode);
CFRelease(downSourceRef)
}
这是我正在执行的侦听和处理程序
CGEventRef onKeyDown(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
NSLog(@"DOWN (%i)", CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode));
// When it matches, I return CGEventCreate(NULL) to stop the event
return event;
}
-另请注意,当我拦截事件(并返回 CGEventCreate(NULL))时,我通常会按一次或多次按键自己的,使用以下代码。请注意,KeyCmd 等只是普通常量的快捷方式。
- (void)sendKey:(KeyCode)code cmd:(BOOL)cmd alt:(BOOL)alt ctl:(BOOL)ctl shift:(BOOL)shift {
CGEventFlags flags = 0;
if (cmd) flags = flags | KeyCmd;
if (alt) flags = flags | KeyAlt;
if (ctl) flags = flags | KeyCtl;
if (shift) flags = flags | KeyShift;
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState);
CGEventRef keyDownPress = CGEventCreateKeyboardEvent(source, (CGKeyCode)code, YES);
CGEventSetFlags(keyDownPress, flags);
CGEventPost(kCGAnnotatedSessionEventTap, keyDownPress);
CFRelease(keyDownPress);
CFRelease(source);
}
谢谢!
So, I've wasted a bunch of time creating this really cool keyboard macro application. It works great, the only problem is that after a couple minutes, it just stops working. It ceases to get called when I press a key.
I haven't been able to lock it down, but it always takes at least 30 seconds to happen. Usually it won't happen for several minutes. I'll have intercepted and sent out many events by then. The application is still running when it happens.
Here's an example of what I'm doing to listen
-(void)listen {
CFMachPortRef downEventTap = CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionDefault,CGEventMaskBit(kCGEventKeyDown),&onKeyDown,self);
downSourceRef = CFMachPortCreateRunLoopSource(NULL, downEventTap, 0);
CFRelease(downEventTap);
CFRunLoopAddSource(CFRunLoopGetCurrent(), downSourceRef, kCFRunLoopDefaultMode);
CFRelease(downSourceRef)
}
And the handler -
CGEventRef onKeyDown(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
NSLog(@"DOWN (%i)", CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode));
// When it matches, I return CGEventCreate(NULL) to stop the event
return event;
}
Also note that when I intercept an event (and return that CGEventCreate(NULL)
), I usually issue one or more key presses of my own, using the following code. Note that KeyCmd, etc, are just shortcuts to the normal constants.
- (void)sendKey:(KeyCode)code cmd:(BOOL)cmd alt:(BOOL)alt ctl:(BOOL)ctl shift:(BOOL)shift {
CGEventFlags flags = 0;
if (cmd) flags = flags | KeyCmd;
if (alt) flags = flags | KeyAlt;
if (ctl) flags = flags | KeyCtl;
if (shift) flags = flags | KeyShift;
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState);
CGEventRef keyDownPress = CGEventCreateKeyboardEvent(source, (CGKeyCode)code, YES);
CGEventSetFlags(keyDownPress, flags);
CGEventPost(kCGAnnotatedSessionEventTap, keyDownPress);
CFRelease(keyDownPress);
CFRelease(source);
}
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为 Snow Leopard 中有一个错误,如果出现超时,它会阻止你的听众。
在 keyDown 处理程序中,检查以下类型,然后重新启用侦听器。
There is a bug in Snow Leopard, I think, that stops your listener if something times out.
In your keyDown handler, check for the following type, and just re-enable the listener.