Skip to content

Instantly share code, notes, and snippets.

@swillits
Created May 31, 2019 16:59
Show Gist options
  • Save swillits/4d2e4fe479e7810cbfe3610a4b12e74e to your computer and use it in GitHub Desktop.
Save swillits/4d2e4fe479e7810cbfe3610a4b12e74e to your computer and use it in GitHub Desktop.
#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