OSX Cocoa输入源检测变化

时间:2014-09-24 18:57:16

标签: macos cocoa keyboard macos-carbon

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

Switching my keyboard settings to German

我可以调用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);

如果我的输入源是&#34;德语&#34;,那么id最终会成为&#34; com.apple.keylayout.German&#34;,这主要是我想要的。不同的是:

  1. 一旦我的流程开始,TISCopyCurrentKeyboardInputSource()的结果就不会改变?特别是,我可以在循环中调用TISCopyCurrentKeyboardInputSource()并切换输入源,但TISCopyCurrentKeyboardInputSource()会一直返回我的进程开始的输入源。
  2. 我很想在输入源发生变化时收到通知。有没有办法做到这一点?要获得某种通知或某种事件,告诉我输入源已被更改?

1 个答案:

答案 0 :(得分:3)

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

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

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