Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can Mac OS X games receive low-level keyboard input events?

Tags:

Games need low-level access to keyboard input. On Windows, there's DirectInput. But what technology do Mac OS X game developers use?

Obviously, there's enough Mac games which get keyboard input just right, without the drawbacks of the commonly known solutions:

Solution #1: Use keyUp / keyDown events

-(void)keyUp:(NSEvent*)event; -(void)keyDown:(NSEvent*)event; 

Inacceptable drawback: keyDown events are repeated based on the system preference settings for "key repeat rate" and "key repeat delay". This causes an initial keyDown event followed by a pause before it starts repeating at a rate defined by a system preference setting. This solution can not be used for continuous key events.

I wonder if the key repeat behavior can be disabled? I suppose that you could read the first keyDown key, then remember the "key with keyCode x is down" state in your class until the keyUp event is received for that key, thus bypassing the repeat delay and repeat rate issues.

Solution #2: Use Quarts Event Taps

See Quartz Event Services Reference. It seems to be sufficiently low-level.

Inacceptable drawback: requires Assistive Devices to be enabled in system preferences under Universal Access - Keyboard. While this may be on by default, there is no guarantee that it might be turned off on some systems.

I also read that Quartz event taps require the app to run as root, but found no confirmation for this.

Solution #3: Carbon Events / IOKit HID

The Carbon Event Manager Reference is marked as legacy and should not be used for new development.

Inacceptable Drawback: no one knows how long the Carbon events will continue to be supported in future Mac OS versions.

Apart from Carbon being a legacy framework, this still seems to be the best solution. But are there any other drawbacks for using Carbon Events?

Questions:

Which technology do Mac OS X game developers use for receiving low-level keyboard input events? If they use one of the above technologies, how do they work around the drawbacks I mentioned?

UPDATE:

I eventually turned to using the regular NSEvent messages and wrapped them in a neat API for polling the keyboard states.

like image 727
LearnCocos2D Avatar asked Sep 08 '11 13:09

LearnCocos2D


People also ask

How do I get keyboard inputs on my Mac screen?

On your Mac, click the Input menu in the menu bar, then choose Show Keyboard Viewer. If the command isn't shown, choose Apple menu > System Preferences, click Keyboard , click Input Sources, then select “Show Input menu in menu bar.”

What is ABC input source on Mac?

ABC is just the same as US but you don't have an American flag. Some users outside the US may find that preferable. ABC-Extended (formerly called US Extended) is much like US or ABC, but it lets you type a whole lot more accented characters via option key shortcuts.


2 Answers

I have had good luck with #3, but it requires a lot of heavy lifting if you want to support anything beyond the keyboard.

One quick point before we dive in though, Carbon and IOKit HID are two separate thing. Carbon may go away at some point. But IOKit HID is here to stay and just got a nice facelift in 10.5.

For a full example of how this stuff all fits together, take a look at https://github.com/OpenEmu/OpenEmu/blob/master/OpenEmu/OEHIDManager.m. That is a small piece of the puzzle as there are other files in there as well.

The documentation for what you're wanting to do can be found http://developer.apple.com/library/mac/#documentation/DeviceDrivers/Conceptual/HID/new_api_10_5/tn2187.html

Again, this is not going to disappear anytime soon and is completely separate from Carbon and Carbon Events.

like image 104
Joshua Weinberg Avatar answered Sep 19 '22 05:09

Joshua Weinberg


I'm late to this party, but here's my solution for an OSX game I'm writing using Swift. It's very simple, and seems to be working pretty well.

First you can put this code in the controller which is receiving keyboard events:

var keysDown = Set<UInt16>()  override func keyDown(e: NSEvent) {     keysDown.insert(e.keyCode) }  override func keyUp(e: NSEvent) {     keysDown.remove(e.keyCode) } 

Then, other parts of the system can determine if a particular key is down:

if (keysDown.contains(49)) {     // space bar is down } 

Or loop through all the keys which are currently pressed

for char in keysDown {      switch char {      case 49:         // space         player.jump()     case 126:         // up         player.moveForward()     case 124:         // right         player.turnRight()          //   ... etc ...      default:         // during development I have this line so I can easily see which keys have which codes         print(char)     } } 

Note keysDown is a Swift Set, so you don't have to worry about duplicates or ordering. A key is either in the set or it isn't.

I'm not too sure how standardised the keycodes are. But you could offer a keyboard configuration page where the user can type keys for each action, and then save whatever keycode this happened to be.

like image 31
Daniel Howard Avatar answered Sep 21 '22 05:09

Daniel Howard