语音狗子 免费下载

「安全键盘输入」为什么会让语音输入和输入法在终端里静默失效

有一类 macOS 故障特别难查:它完全不报错。

你按住热键想说句话,什么都没发生。没有提示音,菜单栏没变化,没有浮层, 控制台里也没有崩溃日志。工具看上去一切正常,就是不干活。

症状:只在某些 App 获得焦点时发生

典型的表现组合是这样的:

第四条是关键线索。能被「当前哪个窗口有焦点」改变的行为,问题基本不在工具 本身。如果四条都对上,九成是「安全键盘输入」(Secure Keyboard Entry)。

机制:系统把按键事件从 event tap 手里拿走了

终端是 macOS 上最容易让你敲出明文密码的地方——sudo 提示、SSH key 口令、 mysql -p、各种粘贴进去的 token。所以几乎所有终端模拟器都提供了一个防护开关:

iTerm2 的官方文档对这个选项的描述已经把副作用写在明面上了:

When this is enabled, the operating system will prevent other programs running on your computer from being able to see what you are typing. If you're concerned that untrusted programs might try to steal your passwords, you can turn this on, but it may disable global hotkeys in other programs. ——iTerm2 Menu Items 文档

最后半句「may disable global hotkeys in other programs」,就是这整篇文章的内容。

这个开关背后是 macOS 的 Secure Event Input 机制。Apple 的技术文档 TN2150《Using Secure Event Input Fairly》 讲得很直接:它保护键盘输入,使按键事件不会被「键盘拦截进程」截获。

关键在于保护的粒度。TN2150 里记录了一次安全更新带来的行为变化:

The fix for this problem is to stop passing keyboard events to any intercept process whenever any process has enabled secure event input, whether that process is in the foreground or background.

两个 any 很重要:任何一个进程启用了这个状态,系统就对所有拦截进程停止 派发按键事件,不管那个进程在前台还是后台。它不是「终端自己不让你看」, 而是一个会话级的全局闸门。

于是当焦点落在开着这个选项的终端上时,所有靠 event tap 监听按键的程序都收不到 你的按键。不是收到了之后被忽略,是从来没收到过。

为什么是「静默」的:tapCreate 这一步是成功的

这才是它最难排查的地方。

一个靠按键触发的工具,启动时会调用 CGEvent.tapCreate 安装事件监听。在 Secure Event Input 状态下,这个调用本身不会失败——它返回一个有效的 tap 对象,加进 RunLoop 也一切顺利,程序完全有理由认为自己装好了监听。

只是那个回调永远不会被触发。

失败发生在系统的派发环节,而不是工具的调用环节。系统没有给出任何同步的错误 信号,工具自然也无从向你提示。这就是「静默」的全部来源:不是工具偷懒不报错, 是它那一侧确实什么都没看见。

工具要主动调用 IsSecureEventInputEnabled() 去查,才能知道自己正处在这个状态里。 而且这个 API 返回的是「当前有没有任何进程启用了它」,不是「是谁启用的」—— 想做一条有用的提示,还得自己再去找持有者。多数工具没做这一步。

怎么确认:三个办法,从可靠到快捷

1. A/B 测试(最可靠)

切到 TextEdit 或备忘录,把光标放进文本框,再按一次热键。如果在这里好使、 回到终端就不好使,基本可以坐实。这个办法不依赖任何版本相关的实现细节。

2. 看菜单勾选状态

Terminal.app 打开顶部菜单「终端」,看「安全键盘输入」有没有打勾;iTerm2 在 菜单栏 iTerm2 下找同名项,也可以去 Preferences → General 里确认。

3. 命令行查当前持有者

ioreg -l -w 0 | grep SecureInput

没有任何输出,说明此刻大概率没有进程持有这个状态;如果有输出,会带上一个 PID,可以用 ps -p <pid> 看是谁。

要说明的是:这条命令是强提示而非铁证。相关字段挂在 IOKit 的控制台会话信息 里,字段名和存在与否在不同 macOS 版本上有差异,没输出也不等于一定没问题。 拿它做第一轮筛查可以,结论还是以第 1 条的 A/B 测试为准。

怎么解决,以及代价是什么

解决方法很简单:把勾去掉,再试一次热键,通常立刻恢复,不需要重启应用。

但这里值得花三十秒想清楚代价,而不是一关了之。

关掉它,意味着其他程序理论上能够监听你在终端里的输入。这个开关当初被加 进来就是为了防这件事。所以判断标准不是「安全重要不重要」,而是「你的终端里 到底会不会出现明文凭证」:

还有个折中:这个开关是按终端应用独立的,可以只在日常用的那个终端里关掉, 需要敲凭证时换到另一个保持开启的终端。

受影响的远不只语音输入

这是一条系统级规则,对所有依赖 event tap 的程序一视同仁。会一起失灵的包括:

判断一个工具会不会中招,不看它属于哪个类别,只看它靠不靠监听按键来触发。

另外要留意:终端不是唯一会打开这个状态的东西。系统锁屏、登录窗口、浏览器和 系统设置里获得焦点的密码输入框,都会短暂地启用它。更麻烦的是某个应用在异常 路径下启用后忘了关,状态就一直挂着——社区里记录过这类个案,比如 1Password 社区的一则讨论, 以及 openai/codex 上的一个 issue 描述了进程退出后状态仍然挂着、只能注销重登才恢复。这些是特定版本下的用户报告, 不代表这些软件当前的行为,列在这里只为说明:终端菜单里明明没打勾、问题却 依然存在时,该怀疑的是别的进程。

语音狗子自己也一样

得把这句说在明处:语音狗子 用 CGEvent.tapCreate 监听右 Option 键, 因此完全受 Secure Event Input 约束,和上面列的所有工具没有任何区别。 终端开着「安全键盘输入」的时候,你按住右 Option,它什么都收不到。

而且它目前不会主动提示这一点——按住没反应时,屏幕上不会出现任何说明。 这是个已知的体验缺口,不是「我们这边不受影响」。

所以如果你装了语音狗子之后发现终端里按住没动静,先查这个开关,再怀疑别的。


关于在终端里实现语音输入的几种整体思路、以及为什么系统自带听写在终端里 不好使,见 Mac 终端里怎么用语音输入—— 那篇对本文的问题有一个简短版说明,这里是它的展开。