OSX Cocoa 输入源检测变化

Ted*_*ton 0 keyboard macos cocoa macos-carbon

有谁知道如何检测用户何时更改 OSX 中的当前输入源?

将我的键盘设置切换为德语

我可以调用TISCopyCurrentKeyboardInputSource()来找出正在使用哪个输入源 ID,如下所示:

    TISInputSourceRef isource = TISCopyCurrentKeyboardInputSource();
    if ( isource == NULL )
    {
        cerr << "Couldn't get the current input source\n.";
        return -1;
    }

    CFStringRef id = (CFStringRef)TISGetInputSourceProperty(
        isource, 
        kTISPropertyInputSourceID);
    CFRelease(isource);
Run Code Online (Sandbox Code Playgroud)

如果我的输入源是“德语”,那么 id 最终会是“com.apple.keylayout.German”,这主要是我想要的。除了:

  1. 一旦我的过程开始,结果TISCopyCurrentKeyboardInputSource()不会改变吗?特别是,我可以TISCopyCurrentKeyboardInputSource()循环调用并切换输入源,但TISCopyCurrentKeyboardInputSource()不断返回进程开始时的输入源。
  2. 我真的很想在输入源更改时收到通知。有什么办法可以做到这一点吗?想要收到通知或某种事件告诉我输入源已更改?

Ken*_*ses 5

您可以观察到默认 Cocoa 通知中心NSTextInputContextKeyboardSelectionDidChangeNotification发布的通知。NSTextInputContext或者,您可以观察kTISNotifySelectedKeyboardInputSourceChanged通过 Core Foundation 分布式通知中心发送的通知。

但是,任何此类更改都会在应用程序外部的系统进程中启动。然后系统通知每个应用程序进程中的框架。仅当框架被允许运行其事件循环时才能接收此类通知。同样,如果您自己观察分布式通知,则只有在允许运行事件循环(或至少主线程的运行循环)时才会发生这种情况。

因此,这解释了为什么运行重复检查结果的循环TISCopyCurrentKeyboardInputSource()不起作用。您不允许框架监视通知更改的渠道。如果您使用频率足够低的重复计时器而不是循环,以便其他东西有机会运行,并且您将控制权返回到应用程序的事件循环,您将看到更改的结果TISCopyCurrentKeyboardInputSource()