Fix [#20419] OSX Cocoa physical punctuation keys retrieval fix

Cocoa charactersIgnoringModifiers API still takes the Shift key into account. Fix is to use Apple new 10.5 Carbon(!) API that is 64bit compatible to take into account the international keyboard layout when retrieving the physical key pressed/released.
Needed to use an even older API for 10.4 builds.
This commit is contained in:
Damien Plisson
2010-03-15 20:38:04 +00:00
parent 8fdb4d4506
commit c12cfa3775

View File

@@ -29,6 +29,9 @@
#import <Cocoa/Cocoa.h>
/*For the currently not ported to Cocoa keyboard layout functions (64bit & 10.6 compatible)*/
#include <Carbon/Carbon.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/sysctl.h>
@@ -53,9 +56,8 @@
#include "AssertMacros.h"
#pragma mark KeyMap, mouse converters
/* Keycodes from Carbon include file */
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
/* Keycodes not defined in Tiger */
/*
* Summary:
* Virtual keycodes
@@ -203,7 +205,7 @@ enum {
kVK_JIS_Eisu = 0x66,
kVK_JIS_Kana = 0x68
};
#endif
static GHOST_TButtonMask convertButton(int button)
{
@@ -230,7 +232,7 @@ static GHOST_TButtonMask convertButton(int button)
* @param recvChar the character ignoring modifiers (except for shift)
* @return Ghost key code
*/
static GHOST_TKey convertKey(int rawCode, unichar recvChar)
static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction)
{
//printf("\nrecvchar %c 0x%x",recvChar,recvChar);
@@ -350,26 +352,68 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar)
return GHOST_kKeyUnknown;
default:
/*Then detect on character value for "remappable" keys in int'l keyboards*/
/* alphanumerical or punctuation key that is remappable in int'l keyboards */
if ((recvChar >= 'A') && (recvChar <= 'Z')) {
return (GHOST_TKey) (recvChar - 'A' + GHOST_kKeyA);
} else if ((recvChar >= 'a') && (recvChar <= 'z')) {
return (GHOST_TKey) (recvChar - 'a' + GHOST_kKeyA);
} else
switch (recvChar) {
case '-': return GHOST_kKeyMinus;
case '=': return GHOST_kKeyEqual;
case ',': return GHOST_kKeyComma;
case '.': return GHOST_kKeyPeriod;
case '/': return GHOST_kKeySlash;
case ';': return GHOST_kKeySemicolon;
case '\'': return GHOST_kKeyQuote;
case '\\': return GHOST_kKeyBackslash;
case '[': return GHOST_kKeyLeftBracket;
case ']': return GHOST_kKeyRightBracket;
case '`': return GHOST_kKeyAccentGrave;
default:
return GHOST_kKeyUnknown;
} else {
#if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4
KeyboardLayoutRef keyLayout;
UCKeyboardLayout *uchrData;
KLGetCurrentKeyboardLayout(&keyLayout);
KLGetKeyboardLayoutProperty(keyLayout, kKLuchrData, (const void **)
&uchrData);
/*get actual character value of the "remappable" keys in int'l keyboards,
if keyboard layout is not correctly reported (e.g. some non Apple keyboards in Tiger),
then fallback on using the received charactersIgnoringModifiers */
if (uchrData)
{
UInt32 deadKeyState=0;
UniCharCount actualStrLength=0;
UCKeyTranslate(uchrData, rawCode, keyAction, 0,
LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &actualStrLength, &recvChar);
}
#else
/* Leopard and Snow Leopard 64bit compatible API*/
CFDataRef uchrHandle; /*the keyboard layout*/
TISInputSourceRef kbdTISHandle;
kbdTISHandle = TISCopyCurrentKeyboardLayoutInputSource();
uchrHandle = (CFDataRef)TISGetInputSourceProperty(kbdTISHandle,kTISPropertyUnicodeKeyLayoutData);
CFRelease(kbdTISHandle);
/*get actual character value of the "remappable" keys in int'l keyboards,
if keyboard layout is not correctly reported (e.g. some non Apple keyboards in Tiger),
then fallback on using the received charactersIgnoringModifiers */
if (uchrHandle)
{
UInt32 deadKeyState=0;
UniCharCount actualStrLength=0;
UCKeyTranslate((UCKeyboardLayout*)CFDataGetBytePtr(uchrHandle), rawCode, keyAction, 0,
LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &actualStrLength, &recvChar);
}
#endif
switch (recvChar) {
case '-': return GHOST_kKeyMinus;
case '=': return GHOST_kKeyEqual;
case ',': return GHOST_kKeyComma;
case '.': return GHOST_kKeyPeriod;
case '/': return GHOST_kKeySlash;
case ';': return GHOST_kKeySemicolon;
case '\'': return GHOST_kKeyQuote;
case '\\': return GHOST_kKeyBackslash;
case '[': return GHOST_kKeyLeftBracket;
case ']': return GHOST_kKeyRightBracket;
case '`': return GHOST_kKeyAccentGrave;
default:
return GHOST_kKeyUnknown;
}
}
}
return GHOST_kKeyUnknown;
@@ -1573,9 +1617,11 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
charsIgnoringModifiers = [event charactersIgnoringModifiers];
if ([charsIgnoringModifiers length]>0)
keyCode = convertKey([event keyCode],
[charsIgnoringModifiers characterAtIndex:0]);
[charsIgnoringModifiers characterAtIndex:0],
[event type] == NSKeyDown?kUCKeyActionDown:kUCKeyActionUp);
else
keyCode = convertKey([event keyCode],0);
keyCode = convertKey([event keyCode],0,
[event type] == NSKeyDown?kUCKeyActionDown:kUCKeyActionUp);
characters = [event characters];
@@ -1595,9 +1641,10 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr)
if ([event type] == NSKeyDown) {
pushEvent( new GHOST_EventKey([event timestamp]*1000, GHOST_kEventKeyDown, window, keyCode, ascii) );
//printf("\nKey pressed keyCode=%u ascii=%i %c",keyCode,ascii,ascii);
//printf("\nKey down rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c",[event keyCode],[charsIgnoringModifiers length]>0?[charsIgnoringModifiers characterAtIndex:0]:' ',keyCode,ascii,ascii);
} else {
pushEvent( new GHOST_EventKey([event timestamp]*1000, GHOST_kEventKeyUp, window, keyCode, ascii) );
//printf("\nKey up rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c",[event keyCode],[charsIgnoringModifiers length]>0?[charsIgnoringModifiers characterAtIndex:0]:' ',keyCode,ascii,ascii);
}
break;