diff options
Diffstat (limited to 'src/widgets/platforms/mac/qkeymapper_mac.cpp')
-rw-r--r-- | src/widgets/platforms/mac/qkeymapper_mac.cpp | 963 |
1 files changed, 0 insertions, 963 deletions
diff --git a/src/widgets/platforms/mac/qkeymapper_mac.cpp b/src/widgets/platforms/mac/qkeymapper_mac.cpp deleted file mode 100644 index 3cacb098aa..0000000000 --- a/src/widgets/platforms/mac/qkeymapper_mac.cpp +++ /dev/null @@ -1,963 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <private/qt_mac_p.h> -#include <qdebug.h> -#include <qevent.h> -#include <private/qevent_p.h> -#include <qtextcodec.h> -#include <qapplication.h> -#include <qinputcontext.h> -#include <private/qkeymapper_p.h> -#include <private/qapplication_p.h> -#include <private/qmacinputcontext_p.h> - -QT_BEGIN_NAMESPACE - -QT_USE_NAMESPACE - -/***************************************************************************** - QKeyMapper debug facilities - *****************************************************************************/ -//#define DEBUG_KEY_BINDINGS -//#define DEBUG_KEY_BINDINGS_MODIFIERS -//#define DEBUG_KEY_MAPS - -/***************************************************************************** - Internal variables and functions - *****************************************************************************/ -bool qt_mac_eat_unicode_key = false; -extern bool qt_sendSpontaneousEvent(QObject *obj, QEvent *event); //qapplication_mac.cpp - -Q_WIDGETS_EXPORT void qt_mac_secure_keyboard(bool b) -{ - static bool secure = false; - if (b != secure){ - b ? EnableSecureEventInput() : DisableSecureEventInput(); - secure = b; - } -} - -/* - \internal - A Mac KeyboardLayoutItem has 8 possible states: - 1. Unmodified - 2. Shift - 3. Control - 4. Control + Shift - 5. Alt - 6. Alt + Shift - 7. Alt + Control - 8. Alt + Control + Shift - 9. Meta - 10. Meta + Shift - 11. Meta + Control - 12. Meta + Control + Shift - 13. Meta + Alt - 14. Meta + Alt + Shift - 15. Meta + Alt + Control - 16. Meta + Alt + Control + Shift -*/ -struct KeyboardLayoutItem { - bool dirty; - quint32 qtKey[16]; // Can by any Qt::Key_<foo>, or unicode character -}; - -// Possible modifier states. -// NOTE: The order of these states match the order in QKeyMapperPrivate::updatePossibleKeyCodes()! -static const Qt::KeyboardModifiers ModsTbl[] = { - Qt::NoModifier, // 0 - Qt::ShiftModifier, // 1 - Qt::ControlModifier, // 2 - Qt::ControlModifier | Qt::ShiftModifier, // 3 - Qt::AltModifier, // 4 - Qt::AltModifier | Qt::ShiftModifier, // 5 - Qt::AltModifier | Qt::ControlModifier, // 6 - Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7 - Qt::MetaModifier, // 8 - Qt::MetaModifier | Qt::ShiftModifier, // 9 - Qt::MetaModifier | Qt::ControlModifier, // 10 - Qt::MetaModifier | Qt::ControlModifier | Qt::ShiftModifier,// 11 - Qt::MetaModifier | Qt::AltModifier, // 12 - Qt::MetaModifier | Qt::AltModifier | Qt::ShiftModifier, // 13 - Qt::MetaModifier | Qt::AltModifier | Qt::ControlModifier, // 14 - Qt::MetaModifier | Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 15 -}; - -/* key maps */ -struct qt_mac_enum_mapper -{ - int mac_code; - int qt_code; -#if defined(DEBUG_KEY_BINDINGS) -# define QT_MAC_MAP_ENUM(x) x, #x - const char *desc; -#else -# define QT_MAC_MAP_ENUM(x) x -#endif -}; - -//modifiers -static qt_mac_enum_mapper qt_mac_modifier_symbols[] = { - { shiftKey, QT_MAC_MAP_ENUM(Qt::ShiftModifier) }, - { rightShiftKey, QT_MAC_MAP_ENUM(Qt::ShiftModifier) }, - { controlKey, QT_MAC_MAP_ENUM(Qt::MetaModifier) }, - { rightControlKey, QT_MAC_MAP_ENUM(Qt::MetaModifier) }, - { cmdKey, QT_MAC_MAP_ENUM(Qt::ControlModifier) }, - { optionKey, QT_MAC_MAP_ENUM(Qt::AltModifier) }, - { rightOptionKey, QT_MAC_MAP_ENUM(Qt::AltModifier) }, - { kEventKeyModifierNumLockMask, QT_MAC_MAP_ENUM(Qt::KeypadModifier) }, - { 0, QT_MAC_MAP_ENUM(0) } -}; -Qt::KeyboardModifiers qt_mac_get_modifiers(int keys) -{ -#ifdef DEBUG_KEY_BINDINGS_MODIFIERS - qDebug("Qt: internal: **Mapping modifiers: %d (0x%04x)", keys, keys); -#endif - Qt::KeyboardModifiers ret = Qt::NoModifier; - for (int i = 0; qt_mac_modifier_symbols[i].qt_code; i++) { - if (keys & qt_mac_modifier_symbols[i].mac_code) { -#ifdef DEBUG_KEY_BINDINGS_MODIFIERS - qDebug("Qt: internal: got modifier: %s", qt_mac_modifier_symbols[i].desc); -#endif - ret |= Qt::KeyboardModifier(qt_mac_modifier_symbols[i].qt_code); - } - } - if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { - Qt::KeyboardModifiers oldModifiers = ret; - ret &= ~(Qt::MetaModifier | Qt::ControlModifier); - if (oldModifiers & Qt::ControlModifier) - ret |= Qt::MetaModifier; - if (oldModifiers & Qt::MetaModifier) - ret |= Qt::ControlModifier; - } - return ret; -} -static int qt_mac_get_mac_modifiers(Qt::KeyboardModifiers keys) -{ -#ifdef DEBUG_KEY_BINDINGS_MODIFIERS - qDebug("Qt: internal: **Mapping modifiers: %d (0x%04x)", (int)keys, (int)keys); -#endif - int ret = 0; - for (int i = 0; qt_mac_modifier_symbols[i].qt_code; i++) { - if (keys & qt_mac_modifier_symbols[i].qt_code) { -#ifdef DEBUG_KEY_BINDINGS_MODIFIERS - qDebug("Qt: internal: got modifier: %s", qt_mac_modifier_symbols[i].desc); -#endif - ret |= qt_mac_modifier_symbols[i].mac_code; - } - } - - if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { - int oldModifiers = ret; - ret &= ~(controlKeyBit | cmdKeyBit); - if (oldModifiers & controlKeyBit) - ret |= cmdKeyBit; - if (oldModifiers & cmdKeyBit) - ret |= controlKeyBit; - } - return ret; -} -void qt_mac_send_modifiers_changed(quint32 modifiers, QObject *object) -{ - static quint32 cachedModifiers = 0; - quint32 lastModifiers = cachedModifiers, - changedModifiers = lastModifiers ^ modifiers; - cachedModifiers = modifiers; - - //check the bits - static qt_mac_enum_mapper modifier_key_symbols[] = { - { shiftKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Shift) }, - { rightShiftKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Shift) }, //??? - { controlKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Meta) }, - { rightControlKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Meta) }, //??? - { cmdKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Control) }, - { optionKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Alt) }, - { rightOptionKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Alt) }, //??? - { alphaLockBit, QT_MAC_MAP_ENUM(Qt::Key_CapsLock) }, - { kEventKeyModifierNumLockBit, QT_MAC_MAP_ENUM(Qt::Key_NumLock) }, - { 0, QT_MAC_MAP_ENUM(0) } }; - for (int i = 0; i <= 32; i++) { //just check each bit - if (!(changedModifiers & (1 << i))) - continue; - QEvent::Type etype = QEvent::KeyPress; - if (lastModifiers & (1 << i)) - etype = QEvent::KeyRelease; - int key = 0; - for (uint x = 0; modifier_key_symbols[x].mac_code; x++) { - if (modifier_key_symbols[x].mac_code == i) { -#ifdef DEBUG_KEY_BINDINGS_MODIFIERS - qDebug("got modifier changed: %s", modifier_key_symbols[x].desc); -#endif - key = modifier_key_symbols[x].qt_code; - break; - } - } - if (!key) { -#ifdef DEBUG_KEY_BINDINGS_MODIFIERS - qDebug("could not get modifier changed: %d", i); -#endif - continue; - } -#ifdef DEBUG_KEY_BINDINGS_MODIFIERS - qDebug("KeyEvent (modif): Sending %s to %s::%s: %d - 0x%08x", - etype == QEvent::KeyRelease ? "KeyRelease" : "KeyPress", - object ? object->metaObject()->className() : "none", - object ? object->objectName().toLatin1().constData() : "", - key, (int)modifiers); -#endif - QKeyEvent ke(etype, key, qt_mac_get_modifiers(modifiers ^ (1 << i)), QLatin1String("")); - qt_sendSpontaneousEvent(object, &ke); - } -} - -//keyboard keys (non-modifiers) -static qt_mac_enum_mapper qt_mac_keyboard_symbols[] = { - { kHomeCharCode, QT_MAC_MAP_ENUM(Qt::Key_Home) }, - { kEnterCharCode, QT_MAC_MAP_ENUM(Qt::Key_Enter) }, - { kEndCharCode, QT_MAC_MAP_ENUM(Qt::Key_End) }, - { kBackspaceCharCode, QT_MAC_MAP_ENUM(Qt::Key_Backspace) }, - { kTabCharCode, QT_MAC_MAP_ENUM(Qt::Key_Tab) }, - { kPageUpCharCode, QT_MAC_MAP_ENUM(Qt::Key_PageUp) }, - { kPageDownCharCode, QT_MAC_MAP_ENUM(Qt::Key_PageDown) }, - { kReturnCharCode, QT_MAC_MAP_ENUM(Qt::Key_Return) }, - { kEscapeCharCode, QT_MAC_MAP_ENUM(Qt::Key_Escape) }, - { kLeftArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Left) }, - { kRightArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Right) }, - { kUpArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Up) }, - { kDownArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Down) }, - { kHelpCharCode, QT_MAC_MAP_ENUM(Qt::Key_Help) }, - { kDeleteCharCode, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, -//ascii maps, for debug - { ':', QT_MAC_MAP_ENUM(Qt::Key_Colon) }, - { ';', QT_MAC_MAP_ENUM(Qt::Key_Semicolon) }, - { '<', QT_MAC_MAP_ENUM(Qt::Key_Less) }, - { '=', QT_MAC_MAP_ENUM(Qt::Key_Equal) }, - { '>', QT_MAC_MAP_ENUM(Qt::Key_Greater) }, - { '?', QT_MAC_MAP_ENUM(Qt::Key_Question) }, - { '@', QT_MAC_MAP_ENUM(Qt::Key_At) }, - { ' ', QT_MAC_MAP_ENUM(Qt::Key_Space) }, - { '!', QT_MAC_MAP_ENUM(Qt::Key_Exclam) }, - { '"', QT_MAC_MAP_ENUM(Qt::Key_QuoteDbl) }, - { '#', QT_MAC_MAP_ENUM(Qt::Key_NumberSign) }, - { '$', QT_MAC_MAP_ENUM(Qt::Key_Dollar) }, - { '%', QT_MAC_MAP_ENUM(Qt::Key_Percent) }, - { '&', QT_MAC_MAP_ENUM(Qt::Key_Ampersand) }, - { '\'', QT_MAC_MAP_ENUM(Qt::Key_Apostrophe) }, - { '(', QT_MAC_MAP_ENUM(Qt::Key_ParenLeft) }, - { ')', QT_MAC_MAP_ENUM(Qt::Key_ParenRight) }, - { '*', QT_MAC_MAP_ENUM(Qt::Key_Asterisk) }, - { '+', QT_MAC_MAP_ENUM(Qt::Key_Plus) }, - { ',', QT_MAC_MAP_ENUM(Qt::Key_Comma) }, - { '-', QT_MAC_MAP_ENUM(Qt::Key_Minus) }, - { '.', QT_MAC_MAP_ENUM(Qt::Key_Period) }, - { '/', QT_MAC_MAP_ENUM(Qt::Key_Slash) }, - { '[', QT_MAC_MAP_ENUM(Qt::Key_BracketLeft) }, - { ']', QT_MAC_MAP_ENUM(Qt::Key_BracketRight) }, - { '\\', QT_MAC_MAP_ENUM(Qt::Key_Backslash) }, - { '_', QT_MAC_MAP_ENUM(Qt::Key_Underscore) }, - { '`', QT_MAC_MAP_ENUM(Qt::Key_QuoteLeft) }, - { '{', QT_MAC_MAP_ENUM(Qt::Key_BraceLeft) }, - { '}', QT_MAC_MAP_ENUM(Qt::Key_BraceRight) }, - { '|', QT_MAC_MAP_ENUM(Qt::Key_Bar) }, - { '~', QT_MAC_MAP_ENUM(Qt::Key_AsciiTilde) }, - { '^', QT_MAC_MAP_ENUM(Qt::Key_AsciiCircum) }, - { 0, QT_MAC_MAP_ENUM(0) } -}; - -static qt_mac_enum_mapper qt_mac_keyvkey_symbols[] = { //real scan codes - { 122, QT_MAC_MAP_ENUM(Qt::Key_F1) }, - { 120, QT_MAC_MAP_ENUM(Qt::Key_F2) }, - { 99, QT_MAC_MAP_ENUM(Qt::Key_F3) }, - { 118, QT_MAC_MAP_ENUM(Qt::Key_F4) }, - { 96, QT_MAC_MAP_ENUM(Qt::Key_F5) }, - { 97, QT_MAC_MAP_ENUM(Qt::Key_F6) }, - { 98, QT_MAC_MAP_ENUM(Qt::Key_F7) }, - { 100, QT_MAC_MAP_ENUM(Qt::Key_F8) }, - { 101, QT_MAC_MAP_ENUM(Qt::Key_F9) }, - { 109, QT_MAC_MAP_ENUM(Qt::Key_F10) }, - { 103, QT_MAC_MAP_ENUM(Qt::Key_F11) }, - { 111, QT_MAC_MAP_ENUM(Qt::Key_F12) }, - { 105, QT_MAC_MAP_ENUM(Qt::Key_F13) }, - { 107, QT_MAC_MAP_ENUM(Qt::Key_F14) }, - { 113, QT_MAC_MAP_ENUM(Qt::Key_F15) }, - { 106, QT_MAC_MAP_ENUM(Qt::Key_F16) }, - { 0, QT_MAC_MAP_ENUM(0) } -}; - -static qt_mac_enum_mapper qt_mac_private_unicode[] = { - { 0xF700, QT_MAC_MAP_ENUM(Qt::Key_Up) }, //NSUpArrowFunctionKey - { 0xF701, QT_MAC_MAP_ENUM(Qt::Key_Down) }, //NSDownArrowFunctionKey - { 0xF702, QT_MAC_MAP_ENUM(Qt::Key_Left) }, //NSLeftArrowFunctionKey - { 0xF703, QT_MAC_MAP_ENUM(Qt::Key_Right) }, //NSRightArrowFunctionKey - { 0xF727, QT_MAC_MAP_ENUM(Qt::Key_Insert) }, //NSInsertFunctionKey - { 0xF728, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, //NSDeleteFunctionKey - { 0xF729, QT_MAC_MAP_ENUM(Qt::Key_Home) }, //NSHomeFunctionKey - { 0xF72B, QT_MAC_MAP_ENUM(Qt::Key_End) }, //NSEndFunctionKey - { 0xF72C, QT_MAC_MAP_ENUM(Qt::Key_PageUp) }, //NSPageUpFunctionKey - { 0xF72D, QT_MAC_MAP_ENUM(Qt::Key_PageDown) }, //NSPageDownFunctionKey - { 0xF72F, QT_MAC_MAP_ENUM(Qt::Key_ScrollLock) }, //NSScrollLockFunctionKey - { 0xF730, QT_MAC_MAP_ENUM(Qt::Key_Pause) }, //NSPauseFunctionKey - { 0xF731, QT_MAC_MAP_ENUM(Qt::Key_SysReq) }, //NSSysReqFunctionKey - { 0xF735, QT_MAC_MAP_ENUM(Qt::Key_Menu) }, //NSMenuFunctionKey - { 0xF738, QT_MAC_MAP_ENUM(Qt::Key_Print) }, //NSPrintFunctionKey - { 0xF73A, QT_MAC_MAP_ENUM(Qt::Key_Clear) }, //NSClearDisplayFunctionKey - { 0xF73D, QT_MAC_MAP_ENUM(Qt::Key_Insert) }, //NSInsertCharFunctionKey - { 0xF73E, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, //NSDeleteCharFunctionKey - { 0xF741, QT_MAC_MAP_ENUM(Qt::Key_Select) }, //NSSelectFunctionKey - { 0xF742, QT_MAC_MAP_ENUM(Qt::Key_Execute) }, //NSExecuteFunctionKey - { 0xF746, QT_MAC_MAP_ENUM(Qt::Key_Help) }, //NSHelpFunctionKey - { 0xF747, QT_MAC_MAP_ENUM(Qt::Key_Mode_switch) }, //NSModeSwitchFunctionKey - { 0, QT_MAC_MAP_ENUM(0) } -}; - -static int qt_mac_get_key(int modif, const QChar &key, int virtualKey) -{ -#ifdef DEBUG_KEY_BINDINGS - qDebug("**Mapping key: %d (0x%04x) - %d (0x%04x)", key.unicode(), key.unicode(), virtualKey, virtualKey); -#endif - - if (key == kClearCharCode && virtualKey == 0x47) - return Qt::Key_Clear; - - if (key.isDigit()) { -#ifdef DEBUG_KEY_BINDINGS - qDebug("%d: got key: %d", __LINE__, key.digitValue()); -#endif - return key.digitValue() + Qt::Key_0; - } - - if (key.isLetter()) { -#ifdef DEBUG_KEY_BINDINGS - qDebug("%d: got key: %d", __LINE__, (key.toUpper().unicode() - 'A')); -#endif - return (key.toUpper().unicode() - 'A') + Qt::Key_A; - } - if (key.isSymbol()) { -#ifdef DEBUG_KEY_BINDINGS - qDebug("%d: got key: %d", __LINE__, (key.unicode())); -#endif - return key.unicode(); - } - - for (int i = 0; qt_mac_keyboard_symbols[i].qt_code; i++) { - if (qt_mac_keyboard_symbols[i].mac_code == key) { - /* To work like Qt for X11 we issue Backtab when Shift + Tab are pressed */ - if (qt_mac_keyboard_symbols[i].qt_code == Qt::Key_Tab && (modif & Qt::ShiftModifier)) { -#ifdef DEBUG_KEY_BINDINGS - qDebug("%d: got key: Qt::Key_Backtab", __LINE__); -#endif - return Qt::Key_Backtab; - } - -#ifdef DEBUG_KEY_BINDINGS - qDebug("%d: got key: %s", __LINE__, qt_mac_keyboard_symbols[i].desc); -#endif - return qt_mac_keyboard_symbols[i].qt_code; - } - } - - //last ditch try to match the scan code - for (int i = 0; qt_mac_keyvkey_symbols[i].qt_code; i++) { - if (qt_mac_keyvkey_symbols[i].mac_code == virtualKey) { -#ifdef DEBUG_KEY_BINDINGS - qDebug("%d: got key: %s", __LINE__, qt_mac_keyvkey_symbols[i].desc); -#endif - return qt_mac_keyvkey_symbols[i].qt_code; - } - } - - // check if they belong to key codes in private unicode range - if (key >= 0xf700 && key <= 0xf747) { - if (key >= 0xf704 && key <= 0xf726) { - return Qt::Key_F1 + (key.unicode() - 0xf704) ; - } - for (int i = 0; qt_mac_private_unicode[i].qt_code; i++) { - if (qt_mac_private_unicode[i].mac_code == key) { - return qt_mac_private_unicode[i].qt_code; - } - } - - } - - //oh well -#ifdef DEBUG_KEY_BINDINGS - qDebug("Unknown case.. %s:%d %d[%d] %d", __FILE__, __LINE__, key.unicode(), key.toLatin1(), virtualKey); -#endif - return Qt::Key_unknown; -} - -static Boolean qt_KeyEventComparatorProc(EventRef inEvent, void *data) -{ - UInt32 ekind = GetEventKind(inEvent), - eclass = GetEventClass(inEvent); - return (eclass == kEventClassKeyboard && (void *)ekind == data); -} - -static bool translateKeyEventInternal(EventHandlerCallRef er, EventRef keyEvent, int *qtKey, - QChar *outChar, Qt::KeyboardModifiers *outModifiers, bool *outHandled) -{ - 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 { - qWarning("Qt::internal::UCKeyTranslate is returnining %ld %s:%d", - long(err), __FILE__, __LINE__); - } - } -#ifdef Q_OS_MAC32 - else { - // The road less travelled; use KeyTranslate - const void *keyboard_layout; - KeyboardLayoutRef keyLayoutRef = 0; - KLGetCurrentKeyboardLayout(&keyLayoutRef); - err = KLGetKeyboardLayoutProperty(keyLayoutRef, kKLKCHRData, - reinterpret_cast<const void **>(&keyboard_layout)); - - int translatedChar = KeyTranslate(keyboard_layout, (GetCurrentEventKeyModifiers() & - (kEventKeyModifierNumLockMask|shiftKey|cmdKey| - rightShiftKey|alphaLock)) | keyCode, - &tmp_unused_state); - if (!translatedChar) { - if (outHandled) { - qt_mac_eat_unicode_key = false; - if (er) - CallNextEventHandler(er, keyEvent); - *outHandled = qt_mac_eat_unicode_key; - } - return false; - } - - //map it into qt keys - *qtKey = qt_mac_get_key(*outModifiers, QChar(translatedChar), keyCode); - if (*outModifiers & (Qt::AltModifier | Qt::ControlModifier)) { - if (translatedChar & (1 << 7)) //high ascii - translatedChar = 0; - } else { //now get the real ascii value - UInt32 tmp_mod = 0L; - static UInt32 tmp_state = 0L; - if (*outModifiers & Qt::ShiftModifier) - tmp_mod |= shiftKey; - if (*outModifiers & Qt::MetaModifier) - tmp_mod |= controlKey; - if (*outModifiers & Qt::ControlModifier) - tmp_mod |= cmdKey; - if (GetCurrentEventKeyModifiers() & alphaLock) //no Qt mapper - tmp_mod |= alphaLock; - if (*outModifiers & Qt::AltModifier) - tmp_mod |= optionKey; - if (*outModifiers & Qt::KeypadModifier) - tmp_mod |= kEventKeyModifierNumLockMask; - translatedChar = KeyTranslate(keyboard_layout, tmp_mod | keyCode, &tmp_state); - } - { - ByteCount unilen = 0; - if (GetEventParameter(keyEvent, kEventParamKeyUnicodes, typeUnicodeText, 0, 0, &unilen, 0) - == noErr && unilen == 2) { - GetEventParameter(keyEvent, kEventParamKeyUnicodes, typeUnicodeText, 0, unilen, 0, outChar); - } else if (translatedChar) { - static QTextCodec *c = 0; - if (!c) - c = QTextCodec::codecForName("Apple Roman"); - char tmpChar = (char)translatedChar; // **sigh** - *outChar = c->toUnicode(&tmpChar, 1).at(0); - } else { - *qtKey = qt_mac_get_key(*outModifiers, QChar(translatedChar), keyCode); - } - } - } -#endif - if (*qtKey == Qt::Key_unknown) - *qtKey = qt_mac_get_key(*outModifiers, *outChar, keyCode); - return true; -} - -QKeyMapperPrivate::QKeyMapperPrivate() -{ - memset(keyLayout, 0, sizeof(keyLayout)); - keyboard_layout_format.unicode = 0; -#ifdef Q_OS_MAC32 - keyboard_mode = NullMode; -#else - currentInputSource = 0; -#endif -} - -QKeyMapperPrivate::~QKeyMapperPrivate() -{ - deleteLayouts(); -} - -bool -QKeyMapperPrivate::updateKeyboard() -{ - const UCKeyboardLayout *uchrData = 0; -#ifdef Q_OS_MAC32 - KeyboardLayoutRef keyLayoutRef = 0; - KLGetCurrentKeyboardLayout(&keyLayoutRef); - - if (keyboard_mode != NullMode && currentKeyboardLayout == keyLayoutRef) - return false; - - OSStatus err; - if (keyLayoutRef != 0) { - err = KLGetKeyboardLayoutProperty(keyLayoutRef, kKLuchrData, - const_cast<const void **>(reinterpret_cast<const void **>(&uchrData))); - if (err != noErr) { - qWarning("Qt::internal::unable to get unicode keyboardlayout %ld %s:%d", - long(err), __FILE__, __LINE__); - } - } -#else - QCFType<TISInputSourceRef> source = TISCopyCurrentKeyboardInputSource(); - if (keyboard_mode != NullMode && source == currentInputSource) { - return false; - } - Q_ASSERT(source != 0); - CFDataRef data = static_cast<CFDataRef>(TISGetInputSourceProperty(source, - kTISPropertyUnicodeKeyLayoutData)); - uchrData = data ? reinterpret_cast<const UCKeyboardLayout *>(CFDataGetBytePtr(data)) : 0; -#endif - - keyboard_kind = LMGetKbdType(); - if (uchrData) { - keyboard_layout_format.unicode = uchrData; - keyboard_mode = UnicodeMode; - } -#ifdef Q_OS_MAC32 - else { - void *happy; - err = KLGetKeyboardLayoutProperty(keyLayoutRef, kKLKCHRData, - const_cast<const void **>(reinterpret_cast<void **>(&happy))); - if (err != noErr) { - qFatal("Qt::internal::unable to get non-unicode layout, cannot procede %ld %s:%d", - long(err), __FILE__, __LINE__); - } - keyboard_layout_format.other = happy; - keyboard_mode = OtherMode; - } - - currentKeyboardLayout = keyLayoutRef; -#else - currentInputSource = source; -#endif - keyboard_dead = 0; - CFStringRef iso639Code; -#ifdef Q_OS_MAC32 -# ifndef kKLLanguageCode -# define kKLLanguageCode 9 -# endif - KLGetKeyboardLayoutProperty(currentKeyboardLayout, kKLLanguageCode, - reinterpret_cast<const void **>(&iso639Code)); -#else - CFArrayRef array = static_cast<CFArrayRef>(TISGetInputSourceProperty(currentInputSource, kTISPropertyInputSourceLanguages)); - iso639Code = static_cast<CFStringRef>(CFArrayGetValueAtIndex(array, 0)); // Actually a RFC3066bis, but it's close enough -#endif - if (iso639Code) { - keyboardInputLocale = QLocale(QCFString::toQString(iso639Code)); - keyboardInputDirection = keyboardInputLocale.textDirection(); - } else { - keyboardInputLocale = QLocale::c(); - keyboardInputDirection = Qt::LeftToRight; - } - return true; -} - -void -QKeyMapperPrivate::deleteLayouts() -{ - keyboard_mode = NullMode; - for (int i = 0; i < 255; ++i) { - if (keyLayout[i]) { - delete keyLayout[i]; - keyLayout[i] = 0; - } - } -} - -void -QKeyMapperPrivate::clearMappings() -{ - deleteLayouts(); - updateKeyboard(); -} - -QList<int> -QKeyMapperPrivate::possibleKeys(QKeyEvent *e) -{ - QList<int> ret; - - KeyboardLayoutItem *kbItem = keyLayout[e->nativeVirtualKey()]; - if (!kbItem) // Key is not in any keyboard layout (e.g. eisu-key on Japanese keyboard) - return ret; - - int baseKey = kbItem->qtKey[0]; - Qt::KeyboardModifiers keyMods = e->modifiers(); - ret << int(baseKey + keyMods); // The base key is _always_ valid, of course - - for (int i = 1; i < 8; ++i) { - Qt::KeyboardModifiers neededMods = ModsTbl[i]; - int key = kbItem->qtKey[i]; - if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) - ret << int(key + (keyMods & ~neededMods)); - } - - return ret; -} - -bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, EventHandlerCallRef er, EventRef event, - void *info, bool grab) -{ - Q_ASSERT(GetEventClass(event) == kEventClassKeyboard); - bool handled_event=true; - UInt32 ekind = GetEventKind(event); - - // unfortunately modifiers changed event looks quite different, so I have a separate - // code path - if (ekind == kEventRawKeyModifiersChanged) { - //figure out changed modifiers, wish Apple would just send a delta - UInt32 modifiers = 0; - GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, 0, - sizeof(modifiers), 0, &modifiers); - qt_mac_send_modifiers_changed(modifiers, widget); - return true; - } - - QInputContext *currentContext = qApp->inputContext(); - if (currentContext && currentContext->isComposing()) { - if (ekind == kEventRawKeyDown) { - QMacInputContext *context = qobject_cast<QMacInputContext*>(currentContext); - if (context) - context->setLastKeydownEvent(event); - } - return false; - } - // Once we process the key down , we don't need to send the saved event again from - // kEventTextInputUnicodeForKeyEvent, so clear it. - if (currentContext && ekind == kEventRawKeyDown) { - QMacInputContext *context = qobject_cast<QMacInputContext*>(currentContext); - if (context) - context->setLastKeydownEvent(0); - } - - //get modifiers - Qt::KeyboardModifiers modifiers; - int qtKey; - QChar ourChar; - if (translateKeyEventInternal(er, event, &qtKey, &ourChar, &modifiers, - &handled_event) == false) - return handled_event; - QString text(ourChar); - /* This is actually wrong - but unfortunately it is the best that can be - done for now because of the Control/Meta mapping problems */ - if (modifiers & (Qt::ControlModifier | Qt::MetaModifier) - && !qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { - text = QString(); - } - - - if (widget) { - // Try to compress key events. - if (!text.isEmpty() && widget->testAttribute(Qt::WA_KeyCompression)) { - EventTime lastTime = GetEventTime(event); - for (;;) { - EventRef releaseEvent = FindSpecificEventInQueue(GetMainEventQueue(), - qt_KeyEventComparatorProc, - (void*)kEventRawKeyUp); - if (!releaseEvent) - break; - const EventTime releaseTime = GetEventTime(releaseEvent); - if (releaseTime < lastTime) - break; - lastTime = releaseTime; - - EventRef pressEvent = FindSpecificEventInQueue(GetMainEventQueue(), - qt_KeyEventComparatorProc, - (void*)kEventRawKeyDown); - if (!pressEvent) - break; - const EventTime pressTime = GetEventTime(pressEvent); - if (pressTime < lastTime) - break; - lastTime = pressTime; - - Qt::KeyboardModifiers compressMod; - int compressQtKey = 0; - QChar compressChar; - if (translateKeyEventInternal(er, pressEvent, - &compressQtKey, &compressChar, &compressMod, 0) - == false) { - break; - } - // Copied from qapplication_x11.cpp (change both). - - bool stopCompression = - // 1) misc keys - (compressQtKey >= Qt::Key_Escape && compressQtKey <= Qt::Key_SysReq) - // 2) cursor movement - || (compressQtKey >= Qt::Key_Home && compressQtKey <= Qt::Key_PageDown) - // 3) extra keys - || (compressQtKey >= Qt::Key_Super_L && compressQtKey <= Qt::Key_Direction_R) - // 4) something that a) doesn't translate to text or b) translates - // to newline text - || (compressQtKey == 0) - || (compressChar == QLatin1Char('\n')) - || (compressQtKey == Qt::Key_unknown); - - if (compressMod == modifiers && !compressChar.isNull() && !stopCompression) { -#ifdef DEBUG_KEY_BINDINGS - qDebug("compressing away %c", compressChar.toLatin1()); -#endif - text += compressChar; - // Clean up - RemoveEventFromQueue(GetMainEventQueue(), releaseEvent); - RemoveEventFromQueue(GetMainEventQueue(), pressEvent); - } else { -#ifdef DEBUG_KEY_BINDINGS - qDebug("stoping compression.."); -#endif - break; - } - } - } - - // There is no way to get the scan code from carbon. But we cannot use the value 0, since - // it indicates that the event originates from somewhere else than the keyboard - UInt32 macScanCode = 1; - UInt32 macVirtualKey = 0; - GetEventParameter(event, kEventParamKeyCode, typeUInt32, 0, sizeof(macVirtualKey), 0, &macVirtualKey); - UInt32 macModifiers = 0; - GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, 0, - sizeof(macModifiers), 0, &macModifiers); - // The unicode characters in the range 0xF700-0xF747 are reserved - // by Mac OS X for transient use as keyboard function keys. We - // wont send 'text' for such key events. This is done to match - // behavior on other platforms. - unsigned int *unicodeKey = (unsigned int*)info; - if (*unicodeKey >= 0xf700 && *unicodeKey <= 0xf747) - text = QString(); - bool isAccepted; - handled_event = QKeyMapper::sendKeyEvent(widget, grab, - (ekind == kEventRawKeyUp) ? QEvent::KeyRelease : QEvent::KeyPress, - qtKey, modifiers, text, ekind == kEventRawKeyRepeat, 0, - macScanCode, macVirtualKey, macModifiers - ,&isAccepted - ); - *unicodeKey = (unsigned int)isAccepted; - } - return handled_event; -} - -void -QKeyMapperPrivate::updateKeyMap(EventHandlerCallRef, EventRef event, void * - unicodeKey // unicode character from NSEvent (modifiers applied) - ) -{ - UInt32 macVirtualKey = 0; - GetEventParameter(event, kEventParamKeyCode, typeUInt32, 0, sizeof(macVirtualKey), 0, &macVirtualKey); - if (updateKeyboard()) - QKeyMapper::changeKeyboard(); - else if (keyLayout[macVirtualKey]) - return; - - UniCharCount buffer_size = 10; - UniChar buffer[buffer_size]; - keyLayout[macVirtualKey] = new KeyboardLayoutItem; - for (int i = 0; i < 16; ++i) { - UniCharCount out_buffer_size = 0; - keyLayout[macVirtualKey]->qtKey[i] = 0; -#ifdef Q_WS_MAC32 - if (keyboard_mode == UnicodeMode) { -#endif - const UInt32 keyModifier = ((qt_mac_get_mac_modifiers(ModsTbl[i]) >> 8) & 0xFF); - OSStatus err = UCKeyTranslate(keyboard_layout_format.unicode, macVirtualKey, kUCKeyActionDown, keyModifier, - keyboard_kind, 0, &keyboard_dead, buffer_size, &out_buffer_size, buffer); - if (err == noErr && out_buffer_size) { - const QChar unicode(buffer[0]); - int qtkey = qt_mac_get_key(keyModifier, unicode, macVirtualKey); - if (qtkey == Qt::Key_unknown) - qtkey = unicode.unicode(); - keyLayout[macVirtualKey]->qtKey[i] = qtkey; - } -#ifndef Q_WS_MAC32 - else { - const QChar unicode(*((UniChar *)unicodeKey)); - int qtkey = qt_mac_get_key(keyModifier, unicode, macVirtualKey); - if (qtkey == Qt::Key_unknown) - qtkey = unicode.unicode(); - keyLayout[macVirtualKey]->qtKey[i] = qtkey; - } -#endif -#ifdef Q_WS_MAC32 - } else { - const UInt32 keyModifier = (qt_mac_get_mac_modifiers(ModsTbl[i])); - - uchar translatedChar = KeyTranslate(keyboard_layout_format.other, keyModifier | macVirtualKey, &keyboard_dead); - if (translatedChar) { - static QTextCodec *c = 0; - if (!c) - c = QTextCodec::codecForName("Apple Roman"); - const QChar unicode(c->toUnicode((const char *)&translatedChar, 1).at(0)); - int qtkey = qt_mac_get_key(keyModifier, unicode, macVirtualKey); - if (qtkey == Qt::Key_unknown) - qtkey = unicode.unicode(); - keyLayout[macVirtualKey]->qtKey[i] = qtkey; - } - } -#endif - } -#ifdef DEBUG_KEY_MAPS - qDebug("updateKeyMap for virtual key = 0x%02x!", (uint)macVirtualKey); - for (int i = 0; i < 16; ++i) { - qDebug(" [%d] (%d,0x%02x,'%c')", i, - keyLayout[macVirtualKey]->qtKey[i], - keyLayout[macVirtualKey]->qtKey[i], - keyLayout[macVirtualKey]->qtKey[i]); - } -#endif -} - -bool -QKeyMapper::sendKeyEvent(QWidget *widget, bool grab, - QEvent::Type type, int code, Qt::KeyboardModifiers modifiers, - const QString &text, bool autorepeat, int count, - quint32 nativeScanCode, quint32 nativeVirtualKey, - quint32 nativeModifiers, bool *isAccepted) -{ - Q_UNUSED(count); - Q_UNUSED(grab); - - if (widget && widget->isEnabled()) { - bool key_event = true; - if (key_event) { -#if defined(DEBUG_KEY_BINDINGS) || defined(DEBUG_KEY_BINDINGS_MODIFIERS) - qDebug("KeyEvent: Sending %s to %s::%s: %s 0x%08x%s", - type == QEvent::KeyRelease ? "KeyRelease" : "KeyPress", - widget ? widget->metaObject()->className() : "none", - widget ? widget->objectName().toLatin1().constData() : "", - text.toLatin1().constData(), int(modifiers), - autorepeat ? " Repeat" : ""); -#endif - QKeyEventEx ke(type, code, modifiers, text, autorepeat, qMax(1, text.length()), - nativeScanCode, nativeVirtualKey, nativeModifiers); - bool retMe = qt_sendSpontaneousEvent(widget,&ke); - if (isAccepted) - *isAccepted = ke.isAccepted(); - return retMe; - } - } - return false; -} - -QT_END_NAMESPACE |