static UniChar OSKeyCodeToUnicode( UInt16 osKeyCode, bool shift = false ) { // Translate the key code. UniChar uniChar = 0; if( sKeyLayoutKind == kKLKCHRKind ) { // KCHR mapping. void* KCHRData; KLGetKeyboardLayoutProperty( sKeyLayout, kKLKCHRData, ( const void** ) & KCHRData ); UInt16 key = ( osKeyCode & 0x7f ); if( shift ) key |= NSShiftKeyMask; UInt32 keyTranslateState = 0; UInt32 charCode = KeyTranslate( KCHRData, key, &keyTranslateState ); charCode &= 0xff; if( keyTranslateState == 0 && charCode ) uniChar = charCode; } else { // UCHR mapping. UCKeyboardLayout* uchrData; KLGetKeyboardLayoutProperty( sKeyLayout, kKLuchrData, ( const void** ) &uchrData ); UInt32 deadKeyState; UniCharCount actualStringLength; UniChar unicodeString[ 4 ]; UCKeyTranslate( uchrData, osKeyCode, kUCKeyActionDown, ( shift ? 0x02 : 0 ), // Oh yeah... Apple docs are fun... LMGetKbdType(), 0, &deadKeyState, sizeof( unicodeString ) / sizeof( unicodeString[ 0 ] ), &actualStringLength, unicodeString ); if( actualStringLength ) uniChar = unicodeString[ 0 ]; // Well, Unicode is something else, but... } return uniChar; }
//---------------------------------------------------------------------------------------------- void keyboard_layout_bang(t_keyboard_layout *x) { //OSStatus err; KeyboardLayoutRef currentLayoutRef; const void *keyboardName; char cKeyboardName[100]; KLGetCurrentKeyboardLayout(¤tLayoutRef); KLGetKeyboardLayoutProperty(currentLayoutRef, kKLName, (const void **)&keyboardName); CFStringGetCString((CFStringRef)keyboardName, cKeyboardName, 100, kCFStringEncodingASCII); outlet_symbol(x->x_data_outlet, gensym(cKeyboardName)); }
void keyboard_layout_anything(t_keyboard_layout *x, t_symbol *s, short argc, t_atom *argv) { //OSStatus err; KeyboardLayoutRef currentLayoutRef; const void *keyboardName; char cKeyboardName[100]; keyboardName= CFStringCreateWithCString(NULL, s->s_name, kCFStringEncodingASCII); KLGetKeyboardLayoutWithName(keyboardName, ¤tLayoutRef); KLGetKeyboardLayoutProperty(currentLayoutRef, kKLName, (const void **)&keyboardName); CFStringGetCString((CFStringRef)keyboardName, cKeyboardName, 100, kCFStringEncodingASCII); KLSetCurrentKeyboardLayout(currentLayoutRef); //outlet_anything(x->t_out, s, 0, NULL); keyboard_layout_bang(x); }
void OSXKeyState::getKeyMap(synergy::KeyMap& keyMap) { // update keyboard groups if (getGroups(m_groups)) { m_groupMap.clear(); SInt32 numGroups = (SInt32)m_groups.size(); for (SInt32 g = 0; g < numGroups; ++g) { m_groupMap[m_groups[g]] = g; } } UInt32 keyboardType = LMGetKbdType(); for (SInt32 g = 0, n = (SInt32)m_groups.size(); g < n; ++g) { // add special keys getKeyMapForSpecialKeys(keyMap, g); const void* resource; bool layoutValid = false; // add regular keys // try uchr resource first #if defined(MAC_OS_X_VERSION_10_5) CFDataRef resourceRef = (CFDataRef)TISGetInputSourceProperty( m_groups[g], kTISPropertyUnicodeKeyLayoutData); layoutValid = resourceRef != NULL; if (layoutValid) resource = CFDataGetBytePtr(resourceRef); #else layoutValid = KLGetKeyboardLayoutProperty( m_groups[g], kKLuchrData, &resource); #endif if (layoutValid) { CUCHRKeyResource uchr(resource, keyboardType); if (uchr.isValid()) { LOG((CLOG_DEBUG1 "using uchr resource for group %d", g)); getKeyMap(keyMap, g, uchr); continue; } } LOG((CLOG_DEBUG1 "no keyboard resource for group %d", g)); } }
void keyboard_layout_menu(t_keyboard_layout *x) { //OSStatus err; KeyboardLayoutRef currentLayoutRef; const void *keyboardName; char cKeyboardName[100]; CFIndex countOfLayouts; CFIndex i; t_atom name; // TODO this should probably output [menu clear( so other messages work too outlet_anything(x->x_status_outlet, gensym("clear"), 0, NULL); KLGetKeyboardLayoutCount(&countOfLayouts); for(i= 0; i<countOfLayouts; i++) { KLGetKeyboardLayoutAtIndex(i, ¤tLayoutRef); KLGetKeyboardLayoutProperty(currentLayoutRef, kKLName, (const void **)&keyboardName); CFStringGetCString((CFStringRef)keyboardName, cKeyboardName, 100, kCFStringEncodingASCII); SETSYMBOL(&name, gensym(cKeyboardName)); // TODO this should probably output [menu append( so other messages work too outlet_anything(x->x_status_outlet, gensym("append"), 1, &name); } }
static bool translateKeyEventInternal(EventHandlerCallRef er, EventRef keyEvent, int *qtKey, QChar *outChar, Qt::KeyboardModifiers *outModifiers, bool *outHandled) { #if !defined(QT_MAC_USE_COCOA) || defined(Q_OS_MAC64) Q_UNUSED(er); Q_UNUSED(outHandled); #endif const UInt32 ekind = GetEventKind(keyEvent); { UInt32 mac_modifiers = 0; GetEventParameter(keyEvent, kEventParamKeyModifiers, typeUInt32, 0, sizeof(mac_modifiers), 0, &mac_modifiers); #ifdef DEBUG_KEY_BINDINGS_MODIFIERS qDebug("************ Mapping modifiers and key ***********"); #endif *outModifiers = qt_mac_get_modifiers(mac_modifiers); #ifdef DEBUG_KEY_BINDINGS_MODIFIERS qDebug("------------ Mapping modifiers and key -----------"); #endif } //get keycode UInt32 keyCode = 0; GetEventParameter(keyEvent, kEventParamKeyCode, typeUInt32, 0, sizeof(keyCode), 0, &keyCode); //get mac mapping static UInt32 tmp_unused_state = 0L; const UCKeyboardLayout *uchrData = 0; #if defined(Q_OS_MAC32) KeyboardLayoutRef keyLayoutRef = 0; KLGetCurrentKeyboardLayout(&keyLayoutRef); OSStatus err; if (keyLayoutRef != 0) { err = KLGetKeyboardLayoutProperty(keyLayoutRef, kKLuchrData, (reinterpret_cast<const void **>(&uchrData))); if (err != noErr) { qWarning("Qt::internal::unable to get keyboardlayout %ld %s:%d", long(err), __FILE__, __LINE__); } } #else QCFType<TISInputSourceRef> inputSource = TISCopyCurrentKeyboardInputSource(); Q_ASSERT(inputSource != 0); CFDataRef data = static_cast<CFDataRef>(TISGetInputSourceProperty(inputSource, kTISPropertyUnicodeKeyLayoutData)); uchrData = data ? reinterpret_cast<const UCKeyboardLayout *>(CFDataGetBytePtr(data)) : 0; #endif *qtKey = Qt::Key_unknown; if (uchrData) { // The easy stuff; use the unicode stuff! UniChar string[4]; UniCharCount actualLength; UInt32 currentModifiers = GetCurrentEventKeyModifiers(); UInt32 currentModifiersWOAltOrControl = currentModifiers & ~(controlKey | optionKey); int keyAction; switch (ekind) { default: case kEventRawKeyDown: keyAction = kUCKeyActionDown; break; case kEventRawKeyUp: keyAction = kUCKeyActionUp; break; case kEventRawKeyRepeat: keyAction = kUCKeyActionAutoKey; break; } OSStatus err = UCKeyTranslate(uchrData, keyCode, keyAction, ((currentModifiersWOAltOrControl >> 8) & 0xff), LMGetKbdType(), kUCKeyTranslateNoDeadKeysMask, &tmp_unused_state, 4, &actualLength, string); if (err == noErr) { *outChar = QChar(string[0]); *qtKey = qt_mac_get_key(*outModifiers, *outChar, keyCode); if (currentModifiersWOAltOrControl != currentModifiers) { // Now get the real char. err = UCKeyTranslate(uchrData, keyCode, keyAction, ((currentModifiers >> 8) & 0xff), LMGetKbdType(), kUCKeyTranslateNoDeadKeysMask, &tmp_unused_state, 4, &actualLength, string); if (err == noErr) *outChar = QChar(string[0]); } } else {
quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) { UTF16Char ch; // Constants found in NSEvent.h from AppKit.framework if (key == Qt::Key_Up) ch = 0xF700; else if (key == Qt::Key_Down) ch = 0xF701; else if (key == Qt::Key_Left) ch = 0xF702; else if (key == Qt::Key_Right) ch = 0xF703; else if (key >= Qt::Key_F1 && key <= Qt::Key_F35) ch = key - Qt::Key_F1 + 0xF704; else if (key == Qt::Key_Insert) ch = 0xF727; else if (key == Qt::Key_Delete) ch = 0xF728; else if (key == Qt::Key_Home) ch = 0xF729; else if (key == Qt::Key_End) ch = 0xF72B; else if (key == Qt::Key_PageUp) ch = 0xF72C; else if (key == Qt::Key_PageDown) ch = 0xF72D; else if (key == Qt::Key_Print) ch = 0xF72E; else if (key == Qt::Key_ScrollLock) ch = 0xF72F; else if (key == Qt::Key_Pause) ch = 0xF730; else if (key == Qt::Key_SysReq) ch = 0xF731; else if (key == Qt::Key_Stop) ch = 0xF734; else if (key == Qt::Key_Menu) ch = 0xF735; else if (key == Qt::Key_Select) ch = 0xF741; else if (key == Qt::Key_Execute) ch = 0xF742; else if (key == Qt::Key_Help) ch = 0xF746; else if (key == Qt::Key_Mode_switch) ch = 0xF747; else if (key == Qt::Key_Escape) ch = 27; else if (key == Qt::Key_Return) ch = 13; else if (key == Qt::Key_Enter) ch = 3; else if (key == Qt::Key_Tab) ch = 9; else ch = key; KeyboardLayoutRef layout; KeyboardLayoutKind layoutKind; KLGetCurrentKeyboardLayout(&layout); KLGetKeyboardLayoutProperty(layout, kKLKind, const_cast<const void**>(reinterpret_cast<void**>(&layoutKind))); if (layoutKind == kKLKCHRKind) { // no Unicode available if (ch > 255) return 0; char* data; KLGetKeyboardLayoutProperty(layout, kKLKCHRData, const_cast<const void**>(reinterpret_cast<void**>(&data))); int ct = *reinterpret_cast<short*>(data + 258); for (int i = 0; i < ct; i++) { char* keyTable = data + 260 + 128 * i; for (int j = 0; j < 128; j++) { if (keyTable[j] == ch) return j; } } return 0; } char* data; KLGetKeyboardLayoutProperty(layout, kKLuchrData, const_cast<const void**>(reinterpret_cast<void**>(&data))); UCKeyboardLayout* header = reinterpret_cast<UCKeyboardLayout*>(data); UCKeyboardTypeHeader* table = header->keyboardTypeList; for (quint32 i=0; i < header->keyboardTypeCount; i++) { UCKeyStateRecordsIndex* stateRec = 0; if (table[i].keyStateRecordsIndexOffset != 0) { stateRec = reinterpret_cast<UCKeyStateRecordsIndex*>(data + table[i].keyStateRecordsIndexOffset); if (stateRec->keyStateRecordsIndexFormat != kUCKeyStateRecordsIndexFormat) stateRec = 0; } UCKeyToCharTableIndex* charTable = reinterpret_cast<UCKeyToCharTableIndex*>(data + table[i].keyToCharTableIndexOffset); if (charTable->keyToCharTableIndexFormat != kUCKeyToCharTableIndexFormat) continue; for (quint32 j=0; j < charTable->keyToCharTableCount; j++) { UCKeyOutput* keyToChar = reinterpret_cast<UCKeyOutput*>(data + charTable->keyToCharTableOffsets[j]); for (quint32 k=0; k < charTable->keyToCharTableSize; k++) { if (keyToChar[k] & kUCKeyOutputTestForIndexMask) { long idx = keyToChar[k] & kUCKeyOutputGetIndexMask; if (stateRec && idx < stateRec->keyStateRecordCount) { UCKeyStateRecord* rec = reinterpret_cast<UCKeyStateRecord*>(data + stateRec->keyStateRecordOffsets[idx]); if (rec->stateZeroCharData == ch) return k; } } else if (!(keyToChar[k] & kUCKeyOutputSequenceIndexMask) && keyToChar[k] < 0xFFFE) { if (keyToChar[k] == ch) return k; } } // for k } // for j } // for i return 0; }
KeyButton COSXKeyState::mapKeyFromEvent(CKeyIDs& ids, KeyModifierMask* maskOut, EventRef event) const { ids.clear(); // map modifier key if (maskOut != NULL) { KeyModifierMask activeMask = getActiveModifiers(); activeMask &= ~KeyModifierAltGr; *maskOut = activeMask; } // get virtual key UInt32 vkCode; GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(vkCode), NULL, &vkCode); // handle up events UInt32 eventKind = GetEventKind(event); if (eventKind == kEventRawKeyUp) { // the id isn't used. we just need the same button we used on // the key press. note that we don't use or reset the dead key // state; up events should not affect the dead key state. ids.push_back(kKeyNone); return mapVirtualKeyToKeyButton(vkCode); } // check for special keys CVirtualKeyMap::const_iterator i = m_virtualKeyMap.find(vkCode); if (i != m_virtualKeyMap.end()) { m_deadKeyState = 0; ids.push_back(i->second); return mapVirtualKeyToKeyButton(vkCode); } // get keyboard info KeyboardLayoutRef keyboardLayout; OSStatus status = KLGetCurrentKeyboardLayout(&keyboardLayout); if (status != noErr) { return kKeyNone; } // get the event modifiers and remove the command and control // keys. note if we used them though. UInt32 modifiers; GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers); static const UInt32 s_commandModifiers = cmdKey | controlKey | rightControlKey; bool isCommand = ((modifiers & s_commandModifiers) != 0); modifiers &= ~s_commandModifiers; // if we've used a command key then we want the glyph produced without // the option key (i.e. the base glyph). if (isCommand) { modifiers &= ~optionKey; } // translate via uchr resource const void* resource; if (KLGetKeyboardLayoutProperty(keyboardLayout, kKLuchrData, &resource) == noErr) { // choose action UInt16 action; switch (eventKind) { case kEventRawKeyDown: action = kUCKeyActionDown; break; case kEventRawKeyRepeat: action = kUCKeyActionAutoKey; break; default: return 0; } // translate key UniCharCount count; UniChar chars[2]; OSStatus status = UCKeyTranslate((const UCKeyboardLayout*)resource, vkCode & 0xffu, action, (modifiers >> 8) & 0xffu, LMGetKbdType(), 0, &m_deadKeyState, sizeof(chars) / sizeof(chars[0]), &count, chars); // get the characters if (status == 0) { if (count != 0 || m_deadKeyState == 0) { m_deadKeyState = 0; for (UniCharCount i = 0; i < count; ++i) { ids.push_back(CKeyResource::unicharToKeyID(chars[i])); } adjustAltGrModifier(ids, maskOut, isCommand); return mapVirtualKeyToKeyButton(vkCode); } return 0; } }
// This method must be executed from the main runloop to avoid the seemingly random // Exception detected while handling key input. TSMProcessRawKeyCode failed (-192) errors. // CFEqual(CFRunLoopGetCurrent(), CFRunLoopGetMain()) void keycode_to_string(CGEventRef event_ref, UniCharCount size, UniCharCount *length, UniChar *buffer) { #if defined(USE_CARBON_LEGACY) || defined(USE_COREFOUNDATION) #if defined(USE_CARBON_LEGACY) KeyboardLayoutRef curr_keyboard_layout; void *inputData = NULL; if (KLGetCurrentKeyboardLayout(&curr_keyboard_layout) == noErr) { if (KLGetKeyboardLayoutProperty(curr_keyboard_layout, kKLuchrData, (const void **) &inputData) != noErr) { inputData = NULL; } } #elif defined(USE_COREFOUNDATION) TISInputSourceRef curr_keyboard_layout = TISCopyCurrentKeyboardLayoutInputSource(); CFDataRef inputData = NULL; if (curr_keyboard_layout != NULL && CFGetTypeID(curr_keyboard_layout) == TISInputSourceGetTypeID()) { CFDataRef data = (CFDataRef) TISGetInputSourceProperty(curr_keyboard_layout, kTISPropertyUnicodeKeyLayoutData); if (data != NULL && CFGetTypeID(data) == CFDataGetTypeID() && CFDataGetLength(data) > 0) { inputData = (CFDataRef) data; } } // Check if the keyboard layout has changed to see if the dead key state needs to be discarded. if (prev_keyboard_layout != NULL && curr_keyboard_layout != NULL && CFEqual(curr_keyboard_layout, prev_keyboard_layout) == false) { curr_deadkey_state = 0; } // Release the previous keyboard layout. if (prev_keyboard_layout != NULL) { CFRelease(prev_keyboard_layout); } // Set the previous keyboard layout to the current layout. if (curr_keyboard_layout != NULL) { prev_keyboard_layout = curr_keyboard_layout; } #endif if (inputData != NULL) { #ifdef USE_CARBON_LEGACY const UCKeyboardLayout *keyboard_layout = (const UCKeyboardLayout *) inputData; #else const UCKeyboardLayout *keyboard_layout = (const UCKeyboardLayout*) CFDataGetBytePtr(inputData); #endif if (keyboard_layout != NULL) { //Extract keycode and modifier information. CGKeyCode keycode = CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode); CGEventFlags modifiers = CGEventGetFlags(event); // Disable all command modifiers for translation. This is required // so UCKeyTranslate will provide a keysym for the separate event. static const CGEventFlags cmd_modifiers = kCGEventFlagMaskCommand | kCGEventFlagMaskControl | kCGEventFlagMaskAlternate; modifiers &= ~cmd_modifiers; // I don't know why but UCKeyTranslate does not process the // kCGEventFlagMaskAlphaShift (A.K.A. Caps Lock Mask) correctly. // We need to basically turn off the mask and process the capital // letters after UCKeyTranslate(). Think Different, not because it // makes sense but because you want to be a hipster. bool is_caps_lock = modifiers & kCGEventFlagMaskAlphaShift; modifiers &= ~kCGEventFlagMaskAlphaShift; OSStatus status = noErr; if (curr_deadkey_state == 0) { // No previous deadkey, attempt a lookup. status = UCKeyTranslate( keyboard_layout, keycode, kUCKeyActionDown, (modifiers >> 16) & 0xFF, //(modifiers >> 16) & 0xFF, || (modifiers >> 8) & 0xFF, LMGetKbdType(), kNilOptions, //kNilOptions, //kUCKeyTranslateNoDeadKeysMask &curr_deadkey_state, size, length, buffer); } else {
KeyButton OSXKeyState::mapKeyFromEvent(KeyIDs& ids, KeyModifierMask* maskOut, CGEventRef event) const { ids.clear(); // map modifier key if (maskOut != NULL) { KeyModifierMask activeMask = getActiveModifiers(); activeMask &= ~KeyModifierAltGr; *maskOut = activeMask; } // get virtual key UInt32 vkCode = CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode); // handle up events UInt32 eventKind = CGEventGetType(event); if (eventKind == kCGEventKeyUp) { // the id isn't used. we just need the same button we used on // the key press. note that we don't use or reset the dead key // state; up events should not affect the dead key state. ids.push_back(kKeyNone); return mapVirtualKeyToKeyButton(vkCode); } // check for special keys VirtualKeyMap::const_iterator i = m_virtualKeyMap.find(vkCode); if (i != m_virtualKeyMap.end()) { m_deadKeyState = 0; ids.push_back(i->second); return mapVirtualKeyToKeyButton(vkCode); } // get keyboard info #if defined(MAC_OS_X_VERSION_10_5) TISInputSourceRef currentKeyboardLayout = TISCopyCurrentKeyboardLayoutInputSource(); #else KeyboardLayoutRef currentKeyboardLayout; OSStatus status = KLGetCurrentKeyboardLayout(¤tKeyboardLayout); #endif if (currentKeyboardLayout == NULL) { return kKeyNone; } // get the event modifiers and remove the command and control // keys. note if we used them though. // UCKeyTranslate expects old-style Carbon modifiers, so convert. UInt32 modifiers; modifiers = mapModifiersToCarbon(CGEventGetFlags(event)); static const UInt32 s_commandModifiers = cmdKey | controlKey | rightControlKey; bool isCommand = ((modifiers & s_commandModifiers) != 0); modifiers &= ~s_commandModifiers; // if we've used a command key then we want the glyph produced without // the option key (i.e. the base glyph). //if (isCommand) { modifiers &= ~optionKey; //} // choose action UInt16 action; if(eventKind==kCGEventKeyDown) { action = kUCKeyActionDown; } else if(CGEventGetIntegerValueField(event, kCGKeyboardEventAutorepeat)==1) { action = kUCKeyActionAutoKey; } else { return 0; } // translate via uchr resource #if defined(MAC_OS_X_VERSION_10_5) CFDataRef ref = (CFDataRef) TISGetInputSourceProperty(currentKeyboardLayout, kTISPropertyUnicodeKeyLayoutData); const UCKeyboardLayout* layout = (const UCKeyboardLayout*) CFDataGetBytePtr(ref); const bool layoutValid = (layout != NULL); #else const void* resource; int err = KLGetKeyboardLayoutProperty(currentKeyboardLayout, kKLuchrData, &resource); const bool layoutValid = (err == noErr); const UCKeyboardLayout* layout = (const UCKeyboardLayout*)resource; #endif if (layoutValid) { // translate key UniCharCount count; UniChar chars[2]; LOG((CLOG_DEBUG2 "modifiers: %08x", modifiers & 0xffu)); OSStatus status = UCKeyTranslate(layout, vkCode & 0xffu, action, (modifiers >> 8) & 0xffu, LMGetKbdType(), 0, &m_deadKeyState, sizeof(chars) / sizeof(chars[0]), &count, chars); // get the characters if (status == 0) { if (count != 0 || m_deadKeyState == 0) { m_deadKeyState = 0; for (UniCharCount i = 0; i < count; ++i) { ids.push_back(KeyResource::unicharToKeyID(chars[i])); } adjustAltGrModifier(ids, maskOut, isCommand); return mapVirtualKeyToKeyButton(vkCode); } return 0; } } return 0; }
OP_STATUS UKeyTranslate::GetUnicharFromVirtualKey(UInt32 virtualKeyCode, uni_char &outUniChar, UInt8 modifierKeyState) { #ifdef SIXTY_FOUR_BIT UInt32 deadKeyState = 0; OP_STATUS result = OpStatus::ERR; TISInputSourceRef kbInputSourceRef = TISCopyCurrentKeyboardLayoutInputSource(); CFDataRef uchrDataRef = (CFDataRef)TISGetInputSourceProperty(kbInputSourceRef, kTISPropertyUnicodeKeyLayoutData); Boolean existsUchr = ((uchrDataRef != NULL) && (CFDataGetBytePtr(uchrDataRef) != NULL) && (CFDataGetLength(uchrDataRef) != 0)); if (existsUchr) { UniCharCount actualLength = 0; UniChar outChar[2] = {0,0}; OSStatus status = UCKeyTranslate((const UCKeyboardLayout *)CFDataGetBytePtr(uchrDataRef), virtualKeyCode, kUCKeyActionDown, modifierKeyState, LMGetKbdType(), kNilOptions, &deadKeyState, 2, &actualLength, outChar); if (status == noErr && actualLength && outChar[0] != kFunctionKeyCharCode) { outUniChar = outChar[0]; result = OpStatus::OK; } } CFRelease(kbInputSourceRef); return result; #else // !SIXTY_FOUR_BIT static KeyboardLayoutRef lastKbdLayout = 0; static const UCKeyboardLayout* ucharData = NULL; static const void* charData = NULL; KeyboardLayoutRef currentKbdLayout = 0; if (noErr != KLGetCurrentKeyboardLayout(¤tKbdLayout) || !currentKbdLayout) { return OpStatus::ERR; } short keyCode; OSStatus error = noErr; UInt32 deadKeyState = 0; OP_STATUS result = OpStatus::ERR; keyCode = virtualKeyCode; if (!ucharData || (currentKbdLayout != lastKbdLayout)) { // Don't fetch this unless we have to: Because of the KeyScript issue handled below this may in some cases return 0 // KeyScript is an EXPENSIVE call, so by caching ucharData as long as possible we minimise the number of times // we need to call it. error = KLGetKeyboardLayoutProperty(currentKbdLayout, kKLuchrData, (const void**)&ucharData); } if (!ucharData) { static Boolean try_again = true; if (try_again && (smRoman == GetScriptManagerVariable(smKeyScript))) { // This is required for roman scripts in order to get something from KLGetCurrentKeyboardLayout KeyScript(smRoman | smKeyForceKeyScriptMask); error = KLGetKeyboardLayoutProperty(currentKbdLayout, kKLuchrData, (const void**)&ucharData); if (error || !ucharData) try_again = false; } } if ((error == noErr) && (ucharData != 0)) { UniCharCount actualLength = 0; UniChar outChar[2] = {0,0}; charData = NULL; error = UCKeyTranslate(ucharData, (unsigned short)keyCode, kUCKeyActionDown, modifierKeyState, LMGetKbdType(), 0, &deadKeyState, 2, &actualLength, outChar); if (error == noErr && actualLength && outChar[0] != kFunctionKeyCharCode) { outUniChar = outChar[0]; result = OpStatus::OK; #ifdef DEBUG_UNI_KEYSTROKES // if (outUniChar & 0xff00) // fprintf(stderr, "UKC:%x\n", outChar[0]); #endif } #ifdef DEBUG_UNI_KEYSTROKES else { fprintf(stderr, "UKCe:%li-%x-%lu-%x\n", error, outChar[0], virtualKeyCode, modifierKeyState); } if (actualLength != 1) fprintf(stderr, "UKCl:%lu-%x-%x-%lu-%x\n", actualLength, outChar[0], outChar[1], virtualKeyCode, modifierKeyState); #endif } else { #ifdef DEBUG_UNI_KEYSTROKES fprintf(stderr, "KLP:%li\n", error); #endif error = noErr; if (!charData || (currentKbdLayout != lastKbdLayout)) { error = KLGetKeyboardLayoutProperty(currentKbdLayout, kKLKCHRData, &charData); } if ((error == noErr) && (charData != 0)) { unsigned long charcs = KeyTranslate(charData, (keyCode & 0xFF) | (modifierKeyState << 8), &deadKeyState); if (charcs & 0xFF) { char src = charcs & 0x00FF; gTextConverter->ConvertBufferFromMac(&src, 1, &outUniChar, 1); result = OpStatus::OK; } #ifdef DEBUG_UNI_KEYSTROKES else { fprintf(stderr, "KTe\n", outUniChar); } if (charcs & 0xFF0000) { fprintf(stderr, "KTe:%x-%lu-%x\n", charcs, virtualKeyCode, modifierKeyState); } #endif } else { #ifdef DEBUG_UNI_KEYSTROKES fprintf(stderr, "KLPe:%li\n", error); #endif } } lastKbdLayout = currentKbdLayout; return result; #endif // SIXTY_FOUR_BIT }
static void GetKeyboardLayout() { KLGetCurrentKeyboardLayout( &sKeyLayout ); KLGetKeyboardLayoutProperty( sKeyLayout, kKLKind, ( const void** ) &sKeyLayoutKind ); KLGetKeyboardLayoutProperty( sKeyLayout, kKLIdentifier, ( const void** ) &sKeyLayoutID ); }
void updateScancodes() { #ifdef QT_MAC_USE_COCOA TISInputSourceRef layout = TISCopyCurrentKeyboardLayoutInputSource(); if (!layout) { qWarning() << "Error retrieving current layout"; return; } if (layout == lastLayout) { CFRelease(layout); } else { // keyboard layout changed #ifndef NDEBUG const void *name = TISGetInputSourceProperty(layout, kTISPropertyLocalizedName); qDebug() << "Layout changed to: " << CFStringGetCStringPtr((CFStringRef)name, 0); #endif lastLayout = layout; scancodes.clear(); CFDataRef data = static_cast<CFDataRef>(TISGetInputSourceProperty(layout, kTISPropertyUnicodeKeyLayoutData)); const UCKeyboardLayout *ucData = data ? reinterpret_cast<const UCKeyboardLayout *>(CFDataGetBytePtr(data)) : 0; if (!ucData) { qWarning() << "Error retrieving current layout character data"; return; } for (int i = 0; i < 128; ++i) { UInt32 tmpState = 0; UniChar str[4]; UniCharCount actualLength = 0; OSStatus err = UCKeyTranslate(ucData, i, kUCKeyActionDown, 0, LMGetKbdType(), kUCKeyTranslateNoDeadKeysMask, &tmpState, 4, &actualLength, str); if (err != noErr) { qWarning() << "Error translating unicode key" << err; } else { if (str[0] && str[0] != kFunctionKeyCharCode) { scancodes.insert(str[0], i); } } } } #else KeyboardLayoutRef layout; if (KLGetCurrentKeyboardLayout(&layout) != noErr) { qWarning() << "Error retrieving current layout"; } if (layout != lastLayout) { #ifndef NDEBUG void *name; KLGetKeyboardLayoutProperty(layout, kKLName, const_cast<const void **>(&name)); qDebug() << "Layout changed to: " << CFStringGetCStringPtr((CFStringRef) name, 0); #endif lastLayout = layout; scancodes.clear(); void *kchr; if (KLGetKeyboardLayoutProperty(layout, kKLKCHRData, const_cast<const void **>(&kchr)) != noErr) { qWarning() << "Couldn't load active keyboard layout"; } else { for (int i = 0; i < 128; i++) { UInt32 tmpState = 0; UInt32 chr = KeyTranslate(kchr, i, &tmpState); if (chr && chr != kFunctionKeyCharCode) { scancodes.insert(chr, i); } } } } #endif }