【发布时间】:2025-12-11 03:35:01
【问题描述】:
在某些应用程序中,应用程序直接处理键盘快捷键是有意义的,否则这些快捷键会绑定到系统范围的组合。例如,⌘-Space(通常是 Spotlight)或 ⌘-Tab(通常是应用切换器)。这适用于各种 Mac 应用程序,例如 VMWare Fusion、Apple 自己的屏幕共享和远程桌面客户端(分别将事件转发到 VM 或服务器,而不是在本地处理它们),以及应用程序中的一些类似的第三方应用程序商店。
我们想在我们正在开发的应用程序中实现这样的模式,但很难弄清楚如何去做。我应该指出,有问题的应用程序是一个常规的前台应用程序,是沙盒的,任何解决方案都必须符合 App Store 规则。商店中的其他应用程序可以做到这一点意味着这一定是可能的。
明确地说,我们想要:
- 检测并处理所有按键,包括绑定到全局快捷键的按键。
- 防止全局快捷方式触发其全局绑定效果。
Apple 的Event Architecture document 建议前台应用程序应该已经接收到这些事件。 (它只讨论处理诸如电源和弹出按钮之类的早期级别,这很好。)它继续建议,key events document also implies NSApplication 的 sendEvent: 方法是基于检测潜在快捷方式的方法修饰符标志,将它们发送到窗口,如果失败,则发送到菜单栏。它没有明确说明全局绑定快捷方式会发生什么。
我尝试继承 NSApplication 并覆盖 sendEvent:。无论我是否将所有事件传递给超类实现,或者如果我说过滤修饰键事件,当我按下⌘-空格时,我都会收到按下和释放命令 (⌘) 键的事件,而不是空格键。 Spotlight UI 总是弹出。
我没有找到太多关于继承 NSApplication 及其早期事件处理的信息,来自 Apple 或其他公司。我似乎无法找出检测和处理全局快捷方式的级别。
有人可以指点我正确的方向吗?
不起作用的可能解决方案:
我在其他 Stack Overflow 帖子中看到的建议,但不适用于我见过的其他应用程序(并且会违反 App Store 规则):
- 可访问性 API(需要特殊权限)
- 事件点击/挂钩(需要以 root 身份运行)
无论如何,这两种方法都太过分了,因为它们可以让你在所有时间拦截所有事件,而不仅仅是在你的应用程序是前台应用程序时。
NSevent 的addGlobalMonitorForEventsMatchingMask:handler: 同时不会阻止全局快捷方式处理程序为这些事件触发,所以我什至没有费心去尝试。
【问题讨论】:
-
Carbon 框架的
RegisterEventHotKey是否违反了 AppStore 规则?它至少在 10.12 Sierra 中有效。 -
App Store 中有哪些第三方应用可以做到这一点?
-
@vadian 似乎不可能:infincia.com/blog/hotkeys-codepoints-app-store
-
@TheNextman 例如,Remotix VNC & RDP 可以通过系统范围的快捷方式进入被控制的系统,就像苹果自己的屏幕共享一样。
标签: macos cocoa keyboard-shortcuts keyboard-events nsevent