NSEvent keyCode gives a keyboard scan code, which is a hardware specific code representing the physical key. I want to convert the scan code to a virtual key code, which is the logical key based on the users keyboard layout (QWERTY, AZERTY, etc).
In Windows I can do this via MapVirtualKey. What is the OS X equivalent?
The virtual key code is precisely not based on the user's keyboard layout. It indicates which key was pressed, not what character that key would produce nor how it's labeled.
For example,
kVK_ANSI_A
(from Carbon/HIToolbox/Events.h, value0x00
) does not mean the key which produces the 'A' character, it means the key which is in the position that the 'A' key is in an ANSI standard keyboard. If a French keyboard layout is active, that key will produce 'Q'. If the physical keyboard is a French keyboard, that key will probably be labeled 'Q', too.So, the virtual key code is sort of akin to a scan code, but from an idealized, standard keyboard. It is, as noted, hardware-independent. It is also independent of the keyboard layout.
To translate from the virtual key code to a character, you can use
UCKeyTranslate()
. You need the 'uchr' data for the current keyboard layout. You can get that usingTISCopyCurrentKeyboardLayoutInputSource()
and thenTISGetInputSourceProperty()
withkTISPropertyUnicodeKeyLayoutData
as the property key.You also need the keyboard type code. I believe it's still supported to use
LMGetKbdType()
to get that, even though it's no longer documented except in the legacy section. If you don't like that, you can obtain aCGEvent
from theNSEvent
,create aand callCGEventSource
from that usingCGEventCreateSourceFromEvent()
, and then useCGEventSourceGetKeyboardType()
CGEventGetIntegerValueField()
withkCGKeyboardEventKeyboardType
to get the keyboard type.Of course, it's much easier to simply use
-[NSEvent characters]
or-[NSEvent charactersIgnoringModifiers]
. Or, if you're implementing a text view, send key-down events to-[NSResponder interpretKeyEvents:]
(as discussed in Cocoa Event Handling Guide: Handling Key Events) or-[NSTextInputContext handleEvent:]
(as discussed in Cocoa Text Architecture Guide:Text Editing). Either of those will call back to the view with the appropriate action selector, likemoveBackward:
, or with-insertText:
if the keystroke (in context of recent events and the input source) would produce text.