tags:

views:

635

answers:

3

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.

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

Does anybody have any hints on how to do this?

+2  A: 
e.James
Good info. I'd just add that you need “Enable access for assistive devices” enabled to get key events from an event tap also.
Boaz Stuller
Thank you! I didn't realize that was a requirement for event traps. I will add it to my answer.
e.James
Thanks for you answer, but checking "Enable access for assistive devices" is not an option. Quicksilver doesn't require it either so there has to be another possibility.
Kristof
This information is not quite correct, but good nonetheless. CGEventTap does not need assistive devices enabled. It only needs this enabled if you capture the event before it enters the user's current session and your process is not root. User session events can always be captured.
Mecki
@Mecki: Thank you for clarifying that. I'm pretty sure Kristof needs to trap events outside of the application that has keyboard focus. Does that count as being outside of the user's session?
e.James
+1  A: 

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.

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.

Boaz Stuller
My app also requires a full presence so that would mean splitting off my app into a background-only one and a normal one, which would then mean inter application communication and make things more complicated. Quicksilver shows it's not necessary. I'll have to study its code I guess. thx
Kristof
You can do something similar by making your window a non-activating panel, which will (mostly) keep clicks in the panel from activating your app. I suspect this is what Quicksilver is doing, since it has the common associated buglet that table view clicks still activate the app.
Boaz Stuller
A: 

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).

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.

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.

Mecki
You only need assistive device access enabled to register a tap on the key-up and key-down events. All the rest work fine without it. However, given the nature of the original question, it's still likely to be required if he uses event taps for his problem.
Boaz Stuller
Looks like Apple has changed it for 10.5, I could get keydown even without AD enabled in 10.4, as long as I was only capturing them on SessionLevel and not trying to change them - at least that used to be working :(
Mecki