IMKit捕获NSKeyup事件

时间:2014-05-13 00:08:28

标签: cocoa events input-method-kit

作为一项实验,我试图实现以下目标:

  • 让空格键作为修改键 - 就像Shift键一样 - 按住空格键,键入键可以打印不同的字母。释放空格键会将状态恢复正常,只需按下它就像普通空格键一样。

我正在考虑处理keydown和keyup事件,但显然IMKServerInput Protocol中的handleEvent:client:似乎只能捕获按键和鼠标事件。

对可可没有多少经验,我尝试了一些没有成功的方法:

我得出结论,IMKit只能被动地接收事件。 由于它不是应用程序,因此没有keyUp:方法可以覆盖 - AFAIK,IMKit不会继承NSResponder类。

不幸的是,可可的范围过于广泛,而且对于像我这样的新手来说,可用的文章要少得多(或者没有帮助)。

任何人都可以帮助我找到正确的方向吗?

2 个答案:

答案 0 :(得分:1)

我逐个尝试了所有可能的替代方案,并最终通过创建一个全局EventTap来实现它 与CGEventTap

代码基本上如下所示:

// Create an event tap.
CGEventMask eventMask = ((1 << kCGEventKeyDown) | (1 << kCGEventKeyUp));
CFMachPortRef eventTap = CGEventTapCreate(kCGSessionEventTap,
                            kCGHeadInsertEventTap,
                            0,
                            eventMask,
                            myCGEventCallback,
                            NULL);

if (!eventTap) {
    NSLog(@"failed to create event tap\n");
    return NO;
} else {
    // Create a run loop source.
    runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
    // Add to the current run loop.
    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
    // Enable the event tap.
    CGEventTapEnable(eventTap, true);
    return YES;
}

其中myCGEventCallback处理全局状态。

同时以下是我发现的一些内容:

  • 根据The Key-Input Message Sequence文档,在尝试链中的其他一堆处理程序后,应用程序只将keydown事件传递给Input Method Kit。你不能让IMKServerInput'抓住'NSKeyUp事件。只需将NSKeyUpMask添加到recognizedEvents:即可。
  • addLocalMonitorForEventsMatchingMask:handler:CGEventTapCreateForPSN无法捕获此事件。我想这是因为虽然输入方法可以作为一个单独的进程运行,但事件本身是从应用程序中触发的,如TextEdit,并移交给输入`方法。
  • IOHIDManager:用于添加新硬件设备和制作驱动程序。
  • 创建全局EventTap需要使用sudo权限运行进程 - 将输入方法复制到/Library/Input Methods不使用sudo权限运行 - 或将应用程序注册到Accessibility控件。那是在系统偏好设置→安全&amp;隐私→隐私选项卡→小牛队中的辅助功能。

答案 1 :(得分:0)

IMKStateSetting协议的recognizedEvents:方法应该启用NSKeyUp个事件:

- (NSUInteger)recognizedEvents:(id)sender {
    return NSKeyDownMask | NSKeyUpMask;
}
  

客户端调用此方法来检查输入方法是否支持事件。默认实现返回NSKeyDownMask。

但是,在测试中,我的输入法仍然没有捕获NSKeyUp个事件。这似乎是一个错误。

我已经提交了以下雷达,并希望其他人会复制它:

rdar:// 21376535