当我的应用程序不在最前面时,如何在NSStatusWindowLevel窗口中获取键盘事件?

时间:2021-03-31 07:24:37

After creating a translucent window (based on example code by Matt Gemmell) I want to get keyboard events in this window. It seems that there are only keyboard events when my application is the active application while I want keyboard events even when my application isn't active but the window is visible.

在创建半透明窗口(基于Matt Gemmell的示例代码)之后,我想在此窗口中获取键盘事件。当我的应用程序是活动应用程序时,似乎只有键盘事件,而我想要键盘事件,即使我的应用程序未激活但窗口可见。

Basically I want behavior like that provided by the Quicksilver application (by blacktree).

基本上我想要Quicksilver应用程序(blacktree)提供的行为。

Does anybody have any hints on how to do this?

有没有人对如何做到这一点有任何暗示?

3 个解决方案

#1


3  

There are two options:

有两种选择:

  1. Use GetEventMonitorTarget() with a tacked-on Carbon run loop to grab keyboard events. Sample code is available on this page at CocoaDev.

  2. 使用带有固定碳运行循环的GetEventMonitorTarget()来获取键盘事件。 CocoaDev在此页面上提供了示例代码。

  3. Register an event trap with CGEventTapCreate. Sample code can be found in this thread from the Apple developer mailing list.
  4. 使用CGEventTapCreate注册事件陷阱。可以在Apple开发人员邮件列表的此主题中找到示例代码。

Edit: Note that these methods only work if you check off “Enable access for assistive devices” in the Universal Access preference pane.

编辑:请注意,只有在“Universal Access”偏好设置面板中选中“为辅助设备启用访问权限”时,这些方法才有效。

#2


1  

A simpler route that may work better for you is to make your app background-only. The discussion on CocoaDev of the LSUIElement plist key explains how to set it up. Basically, your application will not appear in the dock or the app switcher, and will not replace the current application's menu bar when activated. From a user perspective it's never the 'active' application, but any windows you open can get activated and respond to events normally. The only caveat is that you'll never get to show your menu bar, so you'll probably have to set up an NSStatusItem (one of those icon menus that show up on the right side of the menu bar) to control (i.e. quit, bring up prefs, etc.) your application.

一个更适合您的更简单的路线是让您的应用程序仅限背景。关于LSUIElement plist键的CocoaDev的讨论解释了如何设置它。基本上,您的应用程序不会出现在Dock或应用程序切换器中,并且在激活时不会替换当前应用程序的菜单栏。从用户角度来看,它永远不是“活动”应用程序,但是您打开的任何窗口都可以被激活并正常响应事件。唯一需要注意的是,您永远不会显示菜单栏,因此您可能需要设置一个NSStatusItem(显示在菜单栏右侧的其中一个图标菜单)来控制(即退出) ,提出prefs等)你的申请。

Edit: I completely forgot about the Non-Activating Panel checkbox in Interface Builder. You need to use an NSPanel instead of an NSWindow to get this choice. This setting lets your panel accept clicks and keyboard input without activating your application. I'm betting that some mix of this setting and the Carbon Hot Keys API is what QuickSilver is using for their UI.

编辑:我完全忘记了Interface Builder中的非激活面板复选框。您需要使用NSPanel而不是NSWindow来获得此选择。此设置允许您的面板接受点击和键盘输入而无需激活您的应用程序。我敢打赌,这个设置和Carbon Hot Keys API的混合是QuickSilver用于他们的UI的。

#3


0  

Update:
Apple actually seems to have changed everything again starting with 10.5 BTW (I recently upgraded and my sample code did not work as before).

更新:Apple实际上似乎已经从10.5 BTW开始再次改变了一切(我最近升级了,我的示例代码没有像以前那样工作)。

Now you can indeed only capture keydown events setting up an event tap if you are either root or assistive devices are enabled, regardless on which level you plan to capture and regardless if you selected to capture (which allows you to modify and even discard events) or to be listen only. You can still get information when flags have changed (actually even change these) and other events, but keydown under no other circumstances.

现在,您确实只能捕获设置事件点击的keydown事件,如果您是root或辅助设备已启用,无论您计划捕获哪个级别,无论您选择捕获(允许您修改甚至丢弃事件)或者只是倾听。当标志发生变化(实际上甚至更改这些)和其他事件时,您仍然可以获取信息,但在其他任何情况下都无法获得keydown。

However, using the carbon event handler and the method RegisterEventHotKey() allows you to register a hotkey and you'll get notified when it is pressed, you neither need to be root for that nor do you need anything like assistive devices enabled. I think Quicksilver is probably doing it that way.

但是,使用碳事件处理程序和方法RegisterEventHotKey()允许您注册一个热键,并在按下它时收到通知,您既不需要为root,也不需要启用辅助设备。我认为Quicksilver可能正是这样做的。

#1


3  

There are two options:

有两种选择:

  1. Use GetEventMonitorTarget() with a tacked-on Carbon run loop to grab keyboard events. Sample code is available on this page at CocoaDev.

  2. 使用带有固定碳运行循环的GetEventMonitorTarget()来获取键盘事件。 CocoaDev在此页面上提供了示例代码。

  3. Register an event trap with CGEventTapCreate. Sample code can be found in this thread from the Apple developer mailing list.
  4. 使用CGEventTapCreate注册事件陷阱。可以在Apple开发人员邮件列表的此主题中找到示例代码。

Edit: Note that these methods only work if you check off “Enable access for assistive devices” in the Universal Access preference pane.

编辑:请注意,只有在“Universal Access”偏好设置面板中选中“为辅助设备启用访问权限”时,这些方法才有效。

#2


1  

A simpler route that may work better for you is to make your app background-only. The discussion on CocoaDev of the LSUIElement plist key explains how to set it up. Basically, your application will not appear in the dock or the app switcher, and will not replace the current application's menu bar when activated. From a user perspective it's never the 'active' application, but any windows you open can get activated and respond to events normally. The only caveat is that you'll never get to show your menu bar, so you'll probably have to set up an NSStatusItem (one of those icon menus that show up on the right side of the menu bar) to control (i.e. quit, bring up prefs, etc.) your application.

一个更适合您的更简单的路线是让您的应用程序仅限背景。关于LSUIElement plist键的CocoaDev的讨论解释了如何设置它。基本上,您的应用程序不会出现在Dock或应用程序切换器中,并且在激活时不会替换当前应用程序的菜单栏。从用户角度来看,它永远不是“活动”应用程序,但是您打开的任何窗口都可以被激活并正常响应事件。唯一需要注意的是,您永远不会显示菜单栏,因此您可能需要设置一个NSStatusItem(显示在菜单栏右侧的其中一个图标菜单)来控制(即退出) ,提出prefs等)你的申请。

Edit: I completely forgot about the Non-Activating Panel checkbox in Interface Builder. You need to use an NSPanel instead of an NSWindow to get this choice. This setting lets your panel accept clicks and keyboard input without activating your application. I'm betting that some mix of this setting and the Carbon Hot Keys API is what QuickSilver is using for their UI.

编辑:我完全忘记了Interface Builder中的非激活面板复选框。您需要使用NSPanel而不是NSWindow来获得此选择。此设置允许您的面板接受点击和键盘输入而无需激活您的应用程序。我敢打赌,这个设置和Carbon Hot Keys API的混合是QuickSilver用于他们的UI的。

#3


0  

Update:
Apple actually seems to have changed everything again starting with 10.5 BTW (I recently upgraded and my sample code did not work as before).

更新:Apple实际上似乎已经从10.5 BTW开始再次改变了一切(我最近升级了,我的示例代码没有像以前那样工作)。

Now you can indeed only capture keydown events setting up an event tap if you are either root or assistive devices are enabled, regardless on which level you plan to capture and regardless if you selected to capture (which allows you to modify and even discard events) or to be listen only. You can still get information when flags have changed (actually even change these) and other events, but keydown under no other circumstances.

现在,您确实只能捕获设置事件点击的keydown事件,如果您是root或辅助设备已启用,无论您计划捕获哪个级别,无论您选择捕获(允许您修改甚至丢弃事件)或者只是倾听。当标志发生变化(实际上甚至更改这些)和其他事件时,您仍然可以获取信息,但在其他任何情况下都无法获得keydown。

However, using the carbon event handler and the method RegisterEventHotKey() allows you to register a hotkey and you'll get notified when it is pressed, you neither need to be root for that nor do you need anything like assistive devices enabled. I think Quicksilver is probably doing it that way.

但是,使用碳事件处理程序和方法RegisterEventHotKey()允许您注册一个热键,并在按下它时收到通知,您既不需要为root,也不需要启用辅助设备。我认为Quicksilver可能正是这样做的。