pmd*_*mdj 7 macos cocoa keyboard-shortcuts nsevent keyboard-events
在某些应用程序中,应用程序直接处理键盘快捷键是有意义的,否则键盘快捷键将绑定到系统范围的组合.例如,⌘-Space(通常是Spotlight)或⌘-Tab(通常是app切换器).这适用于各种Mac应用程序,例如VMWare Fusion,Apple自己的屏幕共享和远程桌面客户端(分别将事件转发到VM或服务器,而不是在本地处理它们),以及应用程序中的一些类似的第三方应用程序商店.
我们希望在我们正在开发的应用程序中实现这样的模式,但是很难确定如何做到这一点.我应该指出,有问题的应用程序是一个常规的前台应用程序,是沙箱,任何解决方案都必须符合App Store规则.商店中的其他应用程序可以执行此操作的事实意味着这必须是可能的.
要清楚,我们希望:
Apple的Event Architecture文档表明前台应用程序应该已经接收了这些事件.(这大约只有同期水平搬运东西,如电力会谈和弹出按钮,这是很好的.)它继续提出,而关键事件文件还暗示说NSApplication的sendEvent:方法就是检测基于修正标志潜在的快捷方式,调度他们到窗口,如果失败,到菜单栏.它没有明确说明全局绑定快捷方式会发生什么.
我尝试了子类化NSApplication和重写sendEvent:.无论我是否将所有事件都传递给超类实现,或者如果我说,过滤修饰键事件,当我按⌘-Space时,我会收到按下并释放命令(⌘)键的事件,但不会显示空格键.Spotlight UI总是会弹出.
我没有从Apple或其他方面找到有关子类化NSApplication及其早期事件处理的更多信息.我似乎无法找出检测和处理全局快捷方式的级别.
有人可以指点我正确的方向吗?
可行的解决方案不起作用:
建议我在其他Stack Overflow帖子中看到但不适用于我见过的其他应用程序(这会破坏App Store规则):
这两个会矫枉过正,无论如何,因为他们让你拦截所有的活动在所有时候,不只是当你的应用程序是前台应用程序.
NSevent的addGlobalMonitorForEventsMatchingMask:handler:同时并不妨碍全球快捷方式处理从发射这些事件,所以甚至没有尝试它.
好吧,Cocoa 事件方法和 Quartz 事件点击已经过时了,因为它们要么需要 root 访问权限,要么需要可访问权限,或者不会在 Dock 之前捕获事件。
CarbonPushSymbolicHotKeyMode已被淘汰,因为根据文档,它需要可访问性。
CarbonRegisterEventHotKey可能会被淘汰,因为苹果似乎不允许它(请参阅我对问题的评论中的链接)。然而,即便如此,我测试过,你不能用它来捕获 Command+Tab。
我对它如何工作做了一个快速的概念验证,但是 YMMV:
KeyboardWatcher此答案中的示例类。您需要链接 IOKit。Handle_DeviceEventCallback您提供按下的键。显然你可以根据你的需要修改它SetSystemUIMode阻止任务切换器和 Spotlight。您需要链接 Carbon。SetSystemUIMode(kUIModeContentSuppressed, kUIOptionDisableProcessSwitch);
请注意,这仅在您的应用程序位于前台时有效(可能是您想要的)。我使用跟踪矩形在我的视图上设置了此选项,因此只有当鼠标位于我的视图上时它才会生效(就像在 Remotix 中一样):
- (void)viewDidLoad {
[super viewDidLoad];
NSTrackingArea* trackingArea = [[NSTrackingArea alloc] initWithRect:[self.view bounds] options: (NSTrackingMouseEnteredAndExited |
NSTrackingActiveAlways) owner:self userInfo:nil];
[self.view addTrackingArea:trackingArea];
}
- (void) mouseEntered:(NSEvent*)theEvent {
SetSystemUIMode(kUIModeContentSuppressed, kUIOptionDisableProcessSwitch);
}
- (void) mouseExited:(NSEvent*)theEvent {
SetSystemUIMode(kUIModeNormal, 0);
}
Run Code Online (Sandbox Code Playgroud)
Remotix 似乎链接了 Carbon 和 IOKit,但我看不到它们是否有 USB 授权(我尝试了演示,而不是 App Store 版本)。他们有可能正在做这样的事情。
实现此目的的正常方法是安装 Quartz 事件分接头。但是,要接收针对其他应用程序的事件,您需要(如您所说)成为 root 用户,或者为您的应用程序启用辅助功能访问权限。
在当前的沙箱规则中似乎不可能使用事件点击。这一点在开发者论坛中得到了证实。该链接仅供登录,但引用线程:
是否有机会通过阻止启动 iTunes 来处理来自媒体键的事件。在沙箱之前,可以通过创建 CGEventTap 来实现,但现在沙箱使用 hid-controll 拒绝。
不,目前在应用程序沙箱中不可能实现这一点。
我不确定还有其他方法可以做到这一点;我有兴趣知道 App Store 中的哪些应用程序可以?
VMWare Fusion 显然没有沙盒化,苹果自己的应用程序不受这些规则的约束。请记住,沙盒仅对 2012 年推出后添加的新应用程序强制执行。该日期之前添加的应用程序不会强制执行沙盒。看到这个答案。
我很久以前就解决了这个问题,但我才注意到我从未将其发布在这里。答案最终涉及到CGSSetGlobalHotKeyOperatingMode()。这不是公共 API,但有许多 Mac App Store 应用程序通过混淆函数名称并动态查找来使用它。苹果似乎并不介意。该 API 使用起来非常简单,并且有大量开放示例源代码。
| 归档时间: |
|
| 查看次数: |
1007 次 |
| 最近记录: |