2

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

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

我正在考虑处理 keydown 和 keyup 事件,但显然handleEvent:client:IMKServerInput 协议中似乎只捕获 key down 和 mouse 事件。

没有太多可可经验,我尝试了一些方法但没有成功:

  • 通过互联网档案浏览了技术说明 2128 ,它给了我对 plist 项目的适当解释。仍然,没有关于keyup。
  • 尝试将 NSKeyUpMask 添加到recognizedEvents:IMKStateSetting Protocol,但这似乎也没有捕捉到事件。
  • 使用addLocalMonitorForEventsMatchingMask:handler:进行了一些测试, 但没有任何反应。
  • 未能找到NSFlagsChanged使用空格键触发事件的方法。
  • 阅读有关Quartz Event Service的信息,CGEventTap它似乎处理较低级别的用户输入。还没有走这条路。
  • IOHID 管理器

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

不幸的是,cocoa 太宽泛了,对于像我这样的新手来说,它的文档要少得多(或充满了无用的文档)。

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

4

2 回答 2

1

我一一尝试了所有可能的替代方案,最终通过使用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;
}

wheremyCGEventCallback处理全局状态。

同时,这里有一些我发现的:

  • 根据Key-Input Message Sequence文档,在尝试了链中的其他一堆处理程序之后,应用程序仅将 keydown 事件传递给 Input Method Kit。你不能让IMKServerInput'捕捉' NSKeyUp 事件。仅仅添加一个NSKeyUpMasktorecognizedEvents:是行不通的。
  • addLocalMonitorForEventsMatchingMask:handler:并且CGEventTapCreateForPSN不会抓住事件。我想这是因为尽管输入法可能作为一个单独的进程运行,但事件本身是从应用程序中触发的,如 TextEdit,并移交给 Input `Method.
  • IOHIDManager:用于添加新的硬件设备和制作驱动程序。
  • 创建全局 EventTap 需要使用 sudo 权限运行进程——将输入法复制到/Library/Input Methods不使用 sudo 权限运行——或者将应用程序注册到 Accessibility 控件。那在小牛队的系统偏好设置→安全和隐私→隐私选项卡→辅助功能中。
于 2014-06-08T11:14:23.417 回答
0

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

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

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

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

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

rdar://21376535

于 2015-06-15T02:03:09.870 回答