Created
May 31, 2019 16:59
-
-
Save swillits/4d2e4fe479e7810cbfe3610a4b12e74e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Carbon/Carbon.h> | |
static NSLock * gKeyTranslateLock = nil; | |
CFStringRef LiDTS_CopyTranslateHotKey(UInt16 virtualKeyCode) | |
{ | |
static dispatch_once_t onceToken; | |
dispatch_once(&onceToken, ^{ | |
gKeyTranslateLock = [[NSLock alloc] init]; | |
[gKeyTranslateLock setName:@"Key Translate Lock"]; | |
}); | |
[gKeyTranslateLock lock]; // the keyboard functions aren't threadsafe. | |
OSStatus err = noErr; | |
const UCKeyboardLayout * uchrData = NULL; | |
CFStringRef translatedString = NULL; | |
CFMutableStringRef uppercaseString = NULL; | |
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 | |
// Get a keyboard layout object for the keyboard | |
KeyboardLayoutRef theCurrentLayout=NULL; | |
err = KLGetCurrentKeyboardLayout(&theCurrentLayout); | |
// If there's a layout, then get the unicode keyboard layout data | |
if (noErr == err) { | |
err = KLGetKeyboardLayoutProperty(theCurrentLayout, | |
kKLuchrData, (const void **)&uchrData); | |
} | |
#else | |
TISInputSourceRef currentLayoutRef = TISCopyCurrentKeyboardLayoutInputSource(); | |
if (currentLayoutRef) { | |
CFDataRef uchr = TISGetInputSourceProperty(currentLayoutRef, kTISPropertyUnicodeKeyLayoutData); | |
if (uchr) { | |
uchrData = (const UCKeyboardLayout *)CFDataGetBytePtr(uchr); | |
} | |
} | |
#endif | |
// If we got the uchr / unicode layout data, then... | |
if (err == noErr && uchrData != NULL) { | |
UniChar buf[256]; | |
UniCharCount actualStringLength=0; | |
UInt32 deadKeyState = 0; | |
UCKeyTranslate( | |
uchrData, | |
virtualKeyCode, | |
kUCKeyActionDisplay, | |
cmdKey >> 8, // !!! | |
LMGetKbdType(), | |
kUCKeyTranslateNoDeadKeysMask, | |
&deadKeyState, | |
sizeof(buf)/sizeof(UniChar), | |
&actualStringLength, | |
buf | |
); | |
/* | |
UCKeyTranslate( | |
const UCKeyboardLayout * keyLayoutPtr, | |
UInt16 virtualKeyCode, | |
UInt16 keyAction, | |
UInt32 modifierKeyState, | |
UInt32 keyboardType, | |
OptionBits keyTranslateOptions, | |
UInt32 * deadKeyState, | |
UniCharCount maxStringLength, | |
UniCharCount * actualStringLength, | |
UniChar unicodeString[]) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER; | |
*/ | |
translatedString = CFStringCreateWithCharacters(kCFAllocatorDefault, | |
buf, actualStringLength); | |
} | |
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 | |
// Otherwise fallback to non-unicode keyboard data | |
else { | |
UInt32 chars; | |
UInt32 deadKeyState = 0; | |
TextEncoding keyboardEncoding; | |
const void *kchrData; | |
err = KLGetKeyboardLayoutProperty(theCurrentLayout, | |
kKLKCHRData, &kchrData); | |
chars = KeyTranslate( | |
kchrData, | |
(virtualKeyCode & 0x7F) | cmdKey, // !!! | |
&deadKeyState); | |
err = UpgradeScriptInfoToTextEncoding( | |
(ScriptCode)GetScriptManagerVariable(smKeyScript), | |
kTextLanguageDontCare, | |
kTextRegionDontCare, | |
0, // no font name | |
&keyboardEncoding | |
); | |
// There shouldn't be more than one character if dead key state | |
// was zero? | |
// Accented characters take a single byte in legacy encodings. | |
if (!err) | |
translatedString = CFStringCreateWithBytes(kCFAllocatorDefault, | |
(UInt8*)&chars + 3, 1, keyboardEncoding, FALSE); | |
} | |
#endif | |
done: | |
[gKeyTranslateLock unlock]; | |
if (translatedString) | |
uppercaseString = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, translatedString); | |
if (uppercaseString) | |
CFStringUppercase(uppercaseString, 0); | |
if (translatedString) | |
CFRelease(translatedString); | |
return uppercaseString; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment