src/gui/kernel/qkeymapper_mac.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <private/qt_mac_p.h>
       
    43 #include <qdebug.h>
       
    44 #include <qevent.h>
       
    45 #include <private/qevent_p.h>
       
    46 #include <qtextcodec.h>
       
    47 #include <qapplication.h>
       
    48 #include <qinputcontext.h>
       
    49 #include <private/qkeymapper_p.h>
       
    50 #include <private/qapplication_p.h>
       
    51 #include <private/qmacinputcontext_p.h>
       
    52 
       
    53 QT_BEGIN_NAMESPACE
       
    54 
       
    55 QT_USE_NAMESPACE
       
    56 
       
    57 /*****************************************************************************
       
    58   QKeyMapper debug facilities
       
    59  *****************************************************************************/
       
    60 //#define DEBUG_KEY_BINDINGS
       
    61 //#define DEBUG_KEY_BINDINGS_MODIFIERS
       
    62 //#define DEBUG_KEY_MAPS
       
    63 
       
    64 /*****************************************************************************
       
    65   Internal variables and functions
       
    66  *****************************************************************************/
       
    67 bool qt_mac_eat_unicode_key = false;
       
    68 extern bool qt_sendSpontaneousEvent(QObject *obj, QEvent *event); //qapplication_mac.cpp
       
    69 
       
    70 Q_GUI_EXPORT void qt_mac_secure_keyboard(bool b)
       
    71 {
       
    72     static bool secure = false;
       
    73     if (b != secure){
       
    74         b ? EnableSecureEventInput() : DisableSecureEventInput();
       
    75         secure = b;
       
    76     }
       
    77 }
       
    78 
       
    79 /*
       
    80     \internal
       
    81     A Mac KeyboardLayoutItem has 8 possible states:
       
    82         1. Unmodified
       
    83         2. Shift
       
    84         3. Control
       
    85         4. Control + Shift
       
    86         5. Alt
       
    87         6. Alt + Shift
       
    88         7. Alt + Control
       
    89         8. Alt + Control + Shift
       
    90         9. Meta
       
    91         10. Meta + Shift
       
    92         11. Meta + Control
       
    93         12. Meta + Control + Shift
       
    94         13. Meta + Alt
       
    95         14. Meta + Alt + Shift
       
    96         15. Meta + Alt + Control
       
    97         16. Meta + Alt + Control + Shift
       
    98 */
       
    99 struct KeyboardLayoutItem {
       
   100     bool dirty;
       
   101     quint32 qtKey[16]; // Can by any Qt::Key_<foo>, or unicode character
       
   102 };
       
   103 
       
   104 // Possible modifier states.
       
   105 // NOTE: The order of these states match the order in QKeyMapperPrivate::updatePossibleKeyCodes()!
       
   106 static const Qt::KeyboardModifiers ModsTbl[] = {
       
   107     Qt::NoModifier,                                             // 0
       
   108     Qt::ShiftModifier,                                          // 1
       
   109     Qt::ControlModifier,                                        // 2
       
   110     Qt::ControlModifier | Qt::ShiftModifier,                    // 3
       
   111     Qt::AltModifier,                                            // 4
       
   112     Qt::AltModifier | Qt::ShiftModifier,                        // 5
       
   113     Qt::AltModifier | Qt::ControlModifier,                      // 6
       
   114     Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier,  // 7
       
   115     Qt::MetaModifier,                                           // 8
       
   116     Qt::MetaModifier | Qt::ShiftModifier,                       // 9
       
   117     Qt::MetaModifier | Qt::ControlModifier,                    // 10
       
   118     Qt::MetaModifier | Qt::ControlModifier | Qt::ShiftModifier,// 11
       
   119     Qt::MetaModifier | Qt::AltModifier,                        // 12
       
   120     Qt::MetaModifier | Qt::AltModifier | Qt::ShiftModifier,    // 13
       
   121     Qt::MetaModifier | Qt::AltModifier | Qt::ControlModifier,  // 14
       
   122     Qt::MetaModifier | Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier,  // 15
       
   123 };
       
   124 
       
   125 /* key maps */
       
   126 struct qt_mac_enum_mapper
       
   127 {
       
   128     int mac_code;
       
   129     int qt_code;
       
   130 #if defined(DEBUG_KEY_BINDINGS)
       
   131 #   define QT_MAC_MAP_ENUM(x) x, #x
       
   132     const char *desc;
       
   133 #else
       
   134 #   define QT_MAC_MAP_ENUM(x) x
       
   135 #endif
       
   136 };
       
   137 
       
   138 //modifiers
       
   139 static qt_mac_enum_mapper qt_mac_modifier_symbols[] = {
       
   140     { shiftKey, QT_MAC_MAP_ENUM(Qt::ShiftModifier) },
       
   141     { rightShiftKey, QT_MAC_MAP_ENUM(Qt::ShiftModifier) },
       
   142     { controlKey, QT_MAC_MAP_ENUM(Qt::MetaModifier) },
       
   143     { rightControlKey, QT_MAC_MAP_ENUM(Qt::MetaModifier) },
       
   144     { cmdKey, QT_MAC_MAP_ENUM(Qt::ControlModifier) },
       
   145     { optionKey, QT_MAC_MAP_ENUM(Qt::AltModifier) },
       
   146     { rightOptionKey, QT_MAC_MAP_ENUM(Qt::AltModifier) },
       
   147     { kEventKeyModifierNumLockMask, QT_MAC_MAP_ENUM(Qt::KeypadModifier) },
       
   148     { 0, QT_MAC_MAP_ENUM(0) }
       
   149 };
       
   150 Qt::KeyboardModifiers qt_mac_get_modifiers(int keys)
       
   151 {
       
   152 #ifdef DEBUG_KEY_BINDINGS_MODIFIERS
       
   153     qDebug("Qt: internal: **Mapping modifiers: %d (0x%04x)", keys, keys);
       
   154 #endif
       
   155     Qt::KeyboardModifiers ret = Qt::NoModifier;
       
   156     for (int i = 0; qt_mac_modifier_symbols[i].qt_code; i++) {
       
   157         if (keys & qt_mac_modifier_symbols[i].mac_code) {
       
   158 #ifdef DEBUG_KEY_BINDINGS_MODIFIERS
       
   159             qDebug("Qt: internal: got modifier: %s", qt_mac_modifier_symbols[i].desc);
       
   160 #endif
       
   161             ret |= Qt::KeyboardModifier(qt_mac_modifier_symbols[i].qt_code);
       
   162         }
       
   163     }
       
   164     if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
       
   165         Qt::KeyboardModifiers oldModifiers = ret;
       
   166         ret &= ~(Qt::MetaModifier | Qt::ControlModifier);
       
   167         if (oldModifiers & Qt::ControlModifier)
       
   168             ret |= Qt::MetaModifier;
       
   169         if (oldModifiers & Qt::MetaModifier)
       
   170             ret |= Qt::ControlModifier;
       
   171     }
       
   172     return ret;
       
   173 }
       
   174 static int qt_mac_get_mac_modifiers(Qt::KeyboardModifiers keys)
       
   175 {
       
   176 #ifdef DEBUG_KEY_BINDINGS_MODIFIERS
       
   177     qDebug("Qt: internal: **Mapping modifiers: %d (0x%04x)", (int)keys, (int)keys);
       
   178 #endif
       
   179     int ret = 0;
       
   180     for (int i = 0; qt_mac_modifier_symbols[i].qt_code; i++) {
       
   181         if (keys & qt_mac_modifier_symbols[i].qt_code) {
       
   182 #ifdef DEBUG_KEY_BINDINGS_MODIFIERS
       
   183             qDebug("Qt: internal: got modifier: %s", qt_mac_modifier_symbols[i].desc);
       
   184 #endif
       
   185             ret |= qt_mac_modifier_symbols[i].mac_code;
       
   186         }
       
   187     }
       
   188 
       
   189     if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
       
   190         int oldModifiers = ret;
       
   191         ret &= ~(controlKeyBit | cmdKeyBit);
       
   192         if (oldModifiers & controlKeyBit)
       
   193             ret |= cmdKeyBit;
       
   194         if (oldModifiers & cmdKeyBit)
       
   195             ret |= controlKeyBit;
       
   196     }
       
   197     return ret;
       
   198 }
       
   199 void qt_mac_send_modifiers_changed(quint32 modifiers, QObject *object)
       
   200 {
       
   201     static quint32 cachedModifiers = 0;
       
   202     quint32 lastModifiers = cachedModifiers,
       
   203           changedModifiers = lastModifiers ^ modifiers;
       
   204     cachedModifiers = modifiers;
       
   205 
       
   206     //check the bits
       
   207     static qt_mac_enum_mapper modifier_key_symbols[] = {
       
   208         { shiftKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Shift) },
       
   209         { rightShiftKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Shift) }, //???
       
   210         { controlKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Meta) },
       
   211         { rightControlKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Meta) }, //???
       
   212         { cmdKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Control) },
       
   213         { optionKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Alt) },
       
   214         { rightOptionKeyBit, QT_MAC_MAP_ENUM(Qt::Key_Alt) }, //???
       
   215         { alphaLockBit, QT_MAC_MAP_ENUM(Qt::Key_CapsLock) },
       
   216         { kEventKeyModifierNumLockBit, QT_MAC_MAP_ENUM(Qt::Key_NumLock) },
       
   217         {   0, QT_MAC_MAP_ENUM(0) } };
       
   218     for (int i = 0; i <= 32; i++) { //just check each bit
       
   219         if (!(changedModifiers & (1 << i)))
       
   220             continue;
       
   221         QEvent::Type etype = QEvent::KeyPress;
       
   222         if (lastModifiers & (1 << i))
       
   223             etype = QEvent::KeyRelease;
       
   224         int key = 0;
       
   225         for (uint x = 0; modifier_key_symbols[x].mac_code; x++) {
       
   226             if (modifier_key_symbols[x].mac_code == i) {
       
   227 #ifdef DEBUG_KEY_BINDINGS_MODIFIERS
       
   228                 qDebug("got modifier changed: %s", modifier_key_symbols[x].desc);
       
   229 #endif
       
   230                 key = modifier_key_symbols[x].qt_code;
       
   231                 break;
       
   232             }
       
   233         }
       
   234         if (!key) {
       
   235 #ifdef DEBUG_KEY_BINDINGS_MODIFIERS
       
   236             qDebug("could not get modifier changed: %d", i);
       
   237 #endif
       
   238             continue;
       
   239         }
       
   240 #ifdef DEBUG_KEY_BINDINGS_MODIFIERS
       
   241         qDebug("KeyEvent (modif): Sending %s to %s::%s: %d - 0x%08x",
       
   242                etype == QEvent::KeyRelease ? "KeyRelease" : "KeyPress",
       
   243                object ? object->metaObject()->className() : "none",
       
   244                object ? object->objectName().toLatin1().constData() : "",
       
   245                key, (int)modifiers);
       
   246 #endif
       
   247         QKeyEvent ke(etype, key, qt_mac_get_modifiers(modifiers ^ (1 << i)), QLatin1String(""));
       
   248         qt_sendSpontaneousEvent(object, &ke);
       
   249     }
       
   250 }
       
   251 
       
   252 //keyboard keys (non-modifiers)
       
   253 static qt_mac_enum_mapper qt_mac_keyboard_symbols[] = {
       
   254     { kHomeCharCode, QT_MAC_MAP_ENUM(Qt::Key_Home) },
       
   255     { kEnterCharCode, QT_MAC_MAP_ENUM(Qt::Key_Enter) },
       
   256     { kEndCharCode, QT_MAC_MAP_ENUM(Qt::Key_End) },
       
   257     { kBackspaceCharCode, QT_MAC_MAP_ENUM(Qt::Key_Backspace) },
       
   258     { kTabCharCode, QT_MAC_MAP_ENUM(Qt::Key_Tab) },
       
   259     { kPageUpCharCode, QT_MAC_MAP_ENUM(Qt::Key_PageUp) },
       
   260     { kPageDownCharCode, QT_MAC_MAP_ENUM(Qt::Key_PageDown) },
       
   261     { kReturnCharCode, QT_MAC_MAP_ENUM(Qt::Key_Return) },
       
   262     { kEscapeCharCode, QT_MAC_MAP_ENUM(Qt::Key_Escape) },
       
   263     { kLeftArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Left) },
       
   264     { kRightArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Right) },
       
   265     { kUpArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Up) },
       
   266     { kDownArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Down) },
       
   267     { kHelpCharCode, QT_MAC_MAP_ENUM(Qt::Key_Help) },
       
   268     { kDeleteCharCode, QT_MAC_MAP_ENUM(Qt::Key_Delete) },
       
   269 //ascii maps, for debug
       
   270     { ':', QT_MAC_MAP_ENUM(Qt::Key_Colon) },
       
   271     { ';', QT_MAC_MAP_ENUM(Qt::Key_Semicolon) },
       
   272     { '<', QT_MAC_MAP_ENUM(Qt::Key_Less) },
       
   273     { '=', QT_MAC_MAP_ENUM(Qt::Key_Equal) },
       
   274     { '>', QT_MAC_MAP_ENUM(Qt::Key_Greater) },
       
   275     { '?', QT_MAC_MAP_ENUM(Qt::Key_Question) },
       
   276     { '@', QT_MAC_MAP_ENUM(Qt::Key_At) },
       
   277     { ' ', QT_MAC_MAP_ENUM(Qt::Key_Space) },
       
   278     { '!', QT_MAC_MAP_ENUM(Qt::Key_Exclam) },
       
   279     { '"', QT_MAC_MAP_ENUM(Qt::Key_QuoteDbl) },
       
   280     { '#', QT_MAC_MAP_ENUM(Qt::Key_NumberSign) },
       
   281     { '$', QT_MAC_MAP_ENUM(Qt::Key_Dollar) },
       
   282     { '%', QT_MAC_MAP_ENUM(Qt::Key_Percent) },
       
   283     { '&', QT_MAC_MAP_ENUM(Qt::Key_Ampersand) },
       
   284     { '\'', QT_MAC_MAP_ENUM(Qt::Key_Apostrophe) },
       
   285     { '(', QT_MAC_MAP_ENUM(Qt::Key_ParenLeft) },
       
   286     { ')', QT_MAC_MAP_ENUM(Qt::Key_ParenRight) },
       
   287     { '*', QT_MAC_MAP_ENUM(Qt::Key_Asterisk) },
       
   288     { '+', QT_MAC_MAP_ENUM(Qt::Key_Plus) },
       
   289     { ',', QT_MAC_MAP_ENUM(Qt::Key_Comma) },
       
   290     { '-', QT_MAC_MAP_ENUM(Qt::Key_Minus) },
       
   291     { '.', QT_MAC_MAP_ENUM(Qt::Key_Period) },
       
   292     { '/', QT_MAC_MAP_ENUM(Qt::Key_Slash) },
       
   293     { '[', QT_MAC_MAP_ENUM(Qt::Key_BracketLeft) },
       
   294     { ']', QT_MAC_MAP_ENUM(Qt::Key_BracketRight) },
       
   295     { '\\', QT_MAC_MAP_ENUM(Qt::Key_Backslash) },
       
   296     { '_', QT_MAC_MAP_ENUM(Qt::Key_Underscore) },
       
   297     { '`', QT_MAC_MAP_ENUM(Qt::Key_QuoteLeft) },
       
   298     { '{', QT_MAC_MAP_ENUM(Qt::Key_BraceLeft) },
       
   299     { '}', QT_MAC_MAP_ENUM(Qt::Key_BraceRight) },
       
   300     { '|', QT_MAC_MAP_ENUM(Qt::Key_Bar) },
       
   301     { '~', QT_MAC_MAP_ENUM(Qt::Key_AsciiTilde) },
       
   302     { '^', QT_MAC_MAP_ENUM(Qt::Key_AsciiCircum) },
       
   303     {   0, QT_MAC_MAP_ENUM(0) }
       
   304 };
       
   305 
       
   306 static qt_mac_enum_mapper qt_mac_keyvkey_symbols[] = { //real scan codes
       
   307     { 122, QT_MAC_MAP_ENUM(Qt::Key_F1) },
       
   308     { 120, QT_MAC_MAP_ENUM(Qt::Key_F2) },
       
   309     { 99,  QT_MAC_MAP_ENUM(Qt::Key_F3) },
       
   310     { 118, QT_MAC_MAP_ENUM(Qt::Key_F4) },
       
   311     { 96,  QT_MAC_MAP_ENUM(Qt::Key_F5) },
       
   312     { 97,  QT_MAC_MAP_ENUM(Qt::Key_F6) },
       
   313     { 98,  QT_MAC_MAP_ENUM(Qt::Key_F7) },
       
   314     { 100, QT_MAC_MAP_ENUM(Qt::Key_F8) },
       
   315     { 101, QT_MAC_MAP_ENUM(Qt::Key_F9) },
       
   316     { 109, QT_MAC_MAP_ENUM(Qt::Key_F10) },
       
   317     { 103, QT_MAC_MAP_ENUM(Qt::Key_F11) },
       
   318     { 111, QT_MAC_MAP_ENUM(Qt::Key_F12) },
       
   319     { 105, QT_MAC_MAP_ENUM(Qt::Key_F13) },
       
   320     { 107, QT_MAC_MAP_ENUM(Qt::Key_F14) },
       
   321     { 113, QT_MAC_MAP_ENUM(Qt::Key_F15) },
       
   322     { 106, QT_MAC_MAP_ENUM(Qt::Key_F16) },
       
   323     {   0, QT_MAC_MAP_ENUM(0) }
       
   324 };
       
   325 
       
   326 static int qt_mac_get_key(int modif, const QChar &key, int virtualKey)
       
   327 {
       
   328 #ifdef DEBUG_KEY_BINDINGS
       
   329     qDebug("**Mapping key: %d (0x%04x) - %d (0x%04x)", key.unicode(), key.unicode(), virtualKey, virtualKey);
       
   330 #endif
       
   331 
       
   332     if (key == kClearCharCode && virtualKey == 0x47)
       
   333         return Qt::Key_Clear;
       
   334 
       
   335     if (key.isDigit()) {
       
   336 #ifdef DEBUG_KEY_BINDINGS
       
   337             qDebug("%d: got key: %d", __LINE__, key.digitValue());
       
   338 #endif
       
   339         return key.digitValue() + Qt::Key_0;
       
   340     }
       
   341 
       
   342     if (key.isLetter()) {
       
   343 #ifdef DEBUG_KEY_BINDINGS
       
   344         qDebug("%d: got key: %d", __LINE__, (key.toUpper().unicode() - 'A'));
       
   345 #endif
       
   346         return (key.toUpper().unicode() - 'A') + Qt::Key_A;
       
   347     }
       
   348     if (key.isSymbol()) {
       
   349 #ifdef DEBUG_KEY_BINDINGS
       
   350         qDebug("%d: got key: %d", __LINE__, (key.unicode()));
       
   351 #endif
       
   352         return key.unicode();
       
   353     }
       
   354 
       
   355     for (int i = 0; qt_mac_keyboard_symbols[i].qt_code; i++) {
       
   356         if (qt_mac_keyboard_symbols[i].mac_code == key) {
       
   357             /* To work like Qt for X11 we issue Backtab when Shift + Tab are pressed */
       
   358             if (qt_mac_keyboard_symbols[i].qt_code == Qt::Key_Tab && (modif & Qt::ShiftModifier)) {
       
   359 #ifdef DEBUG_KEY_BINDINGS
       
   360                 qDebug("%d: got key: Qt::Key_Backtab", __LINE__);
       
   361 #endif
       
   362                 return Qt::Key_Backtab;
       
   363             }
       
   364 
       
   365 #ifdef DEBUG_KEY_BINDINGS
       
   366             qDebug("%d: got key: %s", __LINE__, qt_mac_keyboard_symbols[i].desc);
       
   367 #endif
       
   368             return qt_mac_keyboard_symbols[i].qt_code;
       
   369         }
       
   370     }
       
   371 
       
   372     //last ditch try to match the scan code
       
   373     for (int i = 0; qt_mac_keyvkey_symbols[i].qt_code; i++) {
       
   374         if (qt_mac_keyvkey_symbols[i].mac_code == virtualKey) {
       
   375 #ifdef DEBUG_KEY_BINDINGS
       
   376             qDebug("%d: got key: %s", __LINE__, qt_mac_keyvkey_symbols[i].desc);
       
   377 #endif
       
   378             return qt_mac_keyvkey_symbols[i].qt_code;
       
   379         }
       
   380     }
       
   381 
       
   382     //oh well
       
   383 #ifdef DEBUG_KEY_BINDINGS
       
   384     qDebug("Unknown case.. %s:%d %d[%d] %d", __FILE__, __LINE__, key.unicode(), key.toLatin1(), virtualKey);
       
   385 #endif
       
   386     return Qt::Key_unknown;
       
   387 }
       
   388 
       
   389 static Boolean qt_KeyEventComparatorProc(EventRef inEvent, void *data)
       
   390 {
       
   391     UInt32 ekind = GetEventKind(inEvent),
       
   392            eclass = GetEventClass(inEvent);
       
   393     return (eclass == kEventClassKeyboard && (void *)ekind == data);
       
   394 }
       
   395 
       
   396 static bool translateKeyEventInternal(EventHandlerCallRef er, EventRef keyEvent, int *qtKey,
       
   397                                       QChar *outChar, Qt::KeyboardModifiers *outModifiers, bool *outHandled)
       
   398 {
       
   399 #if !defined(QT_MAC_USE_COCOA) || defined(Q_OS_MAC64)
       
   400     Q_UNUSED(er);
       
   401     Q_UNUSED(outHandled);
       
   402 #endif
       
   403     const UInt32 ekind = GetEventKind(keyEvent);
       
   404     {
       
   405         UInt32 mac_modifiers = 0;
       
   406         GetEventParameter(keyEvent, kEventParamKeyModifiers, typeUInt32, 0,
       
   407                           sizeof(mac_modifiers), 0, &mac_modifiers);
       
   408 #ifdef DEBUG_KEY_BINDINGS_MODIFIERS
       
   409         qDebug("************ Mapping modifiers and key ***********");
       
   410 #endif
       
   411         *outModifiers = qt_mac_get_modifiers(mac_modifiers);
       
   412 #ifdef DEBUG_KEY_BINDINGS_MODIFIERS
       
   413         qDebug("------------ Mapping modifiers and key -----------");
       
   414 #endif
       
   415     }
       
   416 
       
   417     //get keycode
       
   418     UInt32 keyCode = 0;
       
   419     GetEventParameter(keyEvent, kEventParamKeyCode, typeUInt32, 0, sizeof(keyCode), 0, &keyCode);
       
   420 
       
   421     //get mac mapping
       
   422     static UInt32 tmp_unused_state = 0L;
       
   423     const UCKeyboardLayout *uchrData = 0;
       
   424 #if defined(Q_OS_MAC32)
       
   425     KeyboardLayoutRef keyLayoutRef = 0;
       
   426     KLGetCurrentKeyboardLayout(&keyLayoutRef);
       
   427     OSStatus err;
       
   428     if (keyLayoutRef != 0) {
       
   429         err = KLGetKeyboardLayoutProperty(keyLayoutRef, kKLuchrData,
       
   430                                   (reinterpret_cast<const void **>(&uchrData)));
       
   431         if (err != noErr) {
       
   432             qWarning("Qt::internal::unable to get keyboardlayout %ld %s:%d",
       
   433                      long(err), __FILE__, __LINE__);
       
   434         }
       
   435     }
       
   436 #else
       
   437     QCFType<TISInputSourceRef> inputSource = TISCopyCurrentKeyboardInputSource();
       
   438     Q_ASSERT(inputSource != 0);
       
   439     CFDataRef data = static_cast<CFDataRef>(TISGetInputSourceProperty(inputSource,
       
   440                                                                  kTISPropertyUnicodeKeyLayoutData));
       
   441     uchrData = data ? reinterpret_cast<const UCKeyboardLayout *>(CFDataGetBytePtr(data)) : 0;
       
   442 #endif
       
   443     *qtKey = Qt::Key_unknown;
       
   444     if (uchrData) {
       
   445         // The easy stuff; use the unicode stuff!
       
   446         UniChar string[4];
       
   447         UniCharCount actualLength;
       
   448         UInt32 currentModifiers = GetCurrentEventKeyModifiers();
       
   449         UInt32 currentModifiersWOAltOrControl = currentModifiers & ~(controlKey | optionKey);
       
   450         int keyAction;
       
   451         switch (ekind) {
       
   452         default:
       
   453         case kEventRawKeyDown:
       
   454             keyAction = kUCKeyActionDown;
       
   455             break;
       
   456         case kEventRawKeyUp:
       
   457             keyAction = kUCKeyActionUp;
       
   458             break;
       
   459         case kEventRawKeyRepeat:
       
   460             keyAction = kUCKeyActionAutoKey;
       
   461             break;
       
   462         }
       
   463         OSStatus err = UCKeyTranslate(uchrData, keyCode, keyAction,
       
   464                                   ((currentModifiersWOAltOrControl >> 8) & 0xff), LMGetKbdType(),
       
   465                                   kUCKeyTranslateNoDeadKeysMask, &tmp_unused_state, 4, &actualLength,
       
   466                                   string);
       
   467         if (err == noErr) {
       
   468             *outChar = QChar(string[0]);
       
   469             *qtKey = qt_mac_get_key(*outModifiers, *outChar, keyCode);
       
   470             if (currentModifiersWOAltOrControl != currentModifiers) {
       
   471                 // Now get the real char.
       
   472                 err = UCKeyTranslate(uchrData, keyCode, keyAction,
       
   473                                      ((currentModifiers >> 8) & 0xff), LMGetKbdType(),
       
   474                                       kUCKeyTranslateNoDeadKeysMask, &tmp_unused_state, 4, &actualLength,
       
   475                                       string);
       
   476                 if (err == noErr)
       
   477                     *outChar = QChar(string[0]);
       
   478             }
       
   479         } else {
       
   480             qWarning("Qt::internal::UCKeyTranslate is returnining %ld %s:%d",
       
   481                      long(err), __FILE__, __LINE__);
       
   482         }
       
   483     }
       
   484 #ifdef Q_OS_MAC32
       
   485     else {
       
   486         // The road less travelled; use KeyTranslate
       
   487         const void *keyboard_layout;
       
   488         KeyboardLayoutRef keyLayoutRef = 0;
       
   489         KLGetCurrentKeyboardLayout(&keyLayoutRef);
       
   490         err = KLGetKeyboardLayoutProperty(keyLayoutRef, kKLKCHRData,
       
   491                                   reinterpret_cast<const void **>(&keyboard_layout));
       
   492 
       
   493         int translatedChar = KeyTranslate(keyboard_layout, (GetCurrentEventKeyModifiers() &
       
   494                                                              (kEventKeyModifierNumLockMask|shiftKey|cmdKey|
       
   495                                                               rightShiftKey|alphaLock)) | keyCode,
       
   496                                            &tmp_unused_state);
       
   497         if (!translatedChar) {
       
   498 #ifdef QT_MAC_USE_COCOA
       
   499             if (outHandled) {
       
   500                 qt_mac_eat_unicode_key = false;
       
   501                 if (er)
       
   502                     CallNextEventHandler(er, keyEvent);
       
   503                 *outHandled = qt_mac_eat_unicode_key;
       
   504             }
       
   505 #endif
       
   506             return false;
       
   507         }
       
   508 
       
   509         //map it into qt keys
       
   510         *qtKey = qt_mac_get_key(*outModifiers, QChar(translatedChar), keyCode);
       
   511         if (*outModifiers & (Qt::AltModifier | Qt::ControlModifier)) {
       
   512             if (translatedChar & (1 << 7)) //high ascii
       
   513                 translatedChar = 0;
       
   514         } else {          //now get the real ascii value
       
   515             UInt32 tmp_mod = 0L;
       
   516             static UInt32 tmp_state = 0L;
       
   517             if (*outModifiers & Qt::ShiftModifier)
       
   518                 tmp_mod |= shiftKey;
       
   519             if (*outModifiers & Qt::MetaModifier)
       
   520                 tmp_mod |= controlKey;
       
   521             if (*outModifiers & Qt::ControlModifier)
       
   522                 tmp_mod |= cmdKey;
       
   523             if (GetCurrentEventKeyModifiers() & alphaLock) //no Qt mapper
       
   524                 tmp_mod |= alphaLock;
       
   525             if (*outModifiers & Qt::AltModifier)
       
   526                 tmp_mod |= optionKey;
       
   527             if (*outModifiers & Qt::KeypadModifier)
       
   528                 tmp_mod |= kEventKeyModifierNumLockMask;
       
   529             translatedChar = KeyTranslate(keyboard_layout, tmp_mod | keyCode, &tmp_state);
       
   530         }
       
   531         {
       
   532             ByteCount unilen = 0;
       
   533             if (GetEventParameter(keyEvent, kEventParamKeyUnicodes, typeUnicodeText, 0, 0, &unilen, 0)
       
   534                     == noErr && unilen == 2) {
       
   535                 GetEventParameter(keyEvent, kEventParamKeyUnicodes, typeUnicodeText, 0, unilen, 0, outChar);
       
   536             } else if (translatedChar) {
       
   537                 static QTextCodec *c = 0;
       
   538                 if (!c)
       
   539                     c = QTextCodec::codecForName("Apple Roman");
       
   540 		char tmpChar = (char)translatedChar; // **sigh**
       
   541                 *outChar = c->toUnicode(&tmpChar, 1).at(0);
       
   542             } else {
       
   543                 *qtKey = qt_mac_get_key(*outModifiers, QChar(translatedChar), keyCode);
       
   544             }
       
   545         }
       
   546     }
       
   547 #endif
       
   548     if (*qtKey == Qt::Key_unknown)
       
   549         *qtKey = qt_mac_get_key(*outModifiers, *outChar, keyCode);
       
   550     return true;
       
   551 }
       
   552 
       
   553 QKeyMapperPrivate::QKeyMapperPrivate()
       
   554 {
       
   555     memset(keyLayout, 0, sizeof(keyLayout));
       
   556     keyboard_layout_format.unicode = 0;
       
   557 #ifdef Q_OS_MAC32
       
   558     keyboard_mode = NullMode;
       
   559 #else
       
   560     currentInputSource = 0;
       
   561 #endif
       
   562 }
       
   563 
       
   564 QKeyMapperPrivate::~QKeyMapperPrivate()
       
   565 {
       
   566     deleteLayouts();
       
   567 }
       
   568 
       
   569 bool
       
   570 QKeyMapperPrivate::updateKeyboard()
       
   571 {
       
   572     const UCKeyboardLayout *uchrData = 0;
       
   573 #ifdef Q_OS_MAC32
       
   574     KeyboardLayoutRef keyLayoutRef = 0;
       
   575     KLGetCurrentKeyboardLayout(&keyLayoutRef);
       
   576 
       
   577     if (keyboard_mode != NullMode && currentKeyboardLayout == keyLayoutRef)
       
   578         return false;
       
   579 
       
   580     OSStatus err;
       
   581     if (keyLayoutRef != 0) {
       
   582         err = KLGetKeyboardLayoutProperty(keyLayoutRef, kKLuchrData,
       
   583                                   const_cast<const void **>(reinterpret_cast<const void **>(&uchrData)));
       
   584         if (err != noErr) {
       
   585             qWarning("Qt::internal::unable to get unicode keyboardlayout %ld %s:%d",
       
   586                      long(err), __FILE__, __LINE__);
       
   587         }
       
   588     }
       
   589 #else
       
   590     QCFType<TISInputSourceRef> source = TISCopyCurrentKeyboardInputSource();
       
   591     if (keyboard_mode != NullMode && source == currentInputSource) {
       
   592         return false;
       
   593     }
       
   594     Q_ASSERT(source != 0);
       
   595     CFDataRef data = static_cast<CFDataRef>(TISGetInputSourceProperty(source,
       
   596                                                                  kTISPropertyUnicodeKeyLayoutData));
       
   597     uchrData = data ? reinterpret_cast<const UCKeyboardLayout *>(CFDataGetBytePtr(data)) : 0;
       
   598 #endif
       
   599 
       
   600     keyboard_kind = LMGetKbdType();
       
   601     if (uchrData) {
       
   602         keyboard_layout_format.unicode = uchrData;
       
   603         keyboard_mode = UnicodeMode;
       
   604     }
       
   605 #ifdef Q_OS_MAC32
       
   606     else {
       
   607         void *happy;
       
   608         err = KLGetKeyboardLayoutProperty(keyLayoutRef, kKLKCHRData,
       
   609                                   const_cast<const void **>(reinterpret_cast<void **>(&happy)));
       
   610         if (err != noErr) {
       
   611             qFatal("Qt::internal::unable to get non-unicode layout, cannot procede %ld %s:%d",
       
   612                      long(err), __FILE__, __LINE__);
       
   613         }
       
   614         keyboard_layout_format.other = happy;
       
   615         keyboard_mode = OtherMode;
       
   616     }
       
   617 
       
   618     currentKeyboardLayout = keyLayoutRef;
       
   619 #else
       
   620     currentInputSource = source;
       
   621 #endif
       
   622     keyboard_dead = 0;
       
   623     CFStringRef iso639Code;
       
   624 #ifdef Q_OS_MAC32
       
   625 # ifndef kKLLanguageCode
       
   626 # define kKLLanguageCode 9
       
   627 # endif
       
   628     KLGetKeyboardLayoutProperty(currentKeyboardLayout, kKLLanguageCode,
       
   629                                 reinterpret_cast<const void **>(&iso639Code));
       
   630 #else
       
   631     CFArrayRef array = static_cast<CFArrayRef>(TISGetInputSourceProperty(currentInputSource, kTISPropertyInputSourceLanguages));
       
   632     iso639Code = static_cast<CFStringRef>(CFArrayGetValueAtIndex(array, 0)); // Actually a RFC3066bis, but it's close enough
       
   633 #endif
       
   634     if (iso639Code) {
       
   635         keyboardInputLocale = QLocale(QCFString::toQString(iso639Code));
       
   636         QString monday = keyboardInputLocale.dayName(1);
       
   637         bool rtl = false;
       
   638         for (int i = 0; i < monday.length(); ++i) {
       
   639             switch (monday.at(i).direction()) {
       
   640             default:
       
   641                 break;
       
   642             case QChar::DirR:
       
   643             case QChar::DirAL:
       
   644             case QChar::DirRLE:
       
   645             case QChar::DirRLO:
       
   646                 rtl = true;
       
   647                 break;
       
   648             }
       
   649             if (rtl)
       
   650                 break;
       
   651         }
       
   652         keyboardInputDirection = rtl ? Qt::RightToLeft : Qt::LeftToRight;
       
   653     } else {
       
   654         keyboardInputLocale = QLocale::c();
       
   655         keyboardInputDirection = Qt::LeftToRight;
       
   656     }
       
   657     return true;
       
   658 }
       
   659 
       
   660 void
       
   661 QKeyMapperPrivate::deleteLayouts()
       
   662 {
       
   663     keyboard_mode = NullMode;
       
   664     for (int i = 0; i < 255; ++i) {
       
   665         if (keyLayout[i]) {
       
   666             delete keyLayout[i];
       
   667             keyLayout[i] = 0;
       
   668         }
       
   669     }
       
   670 }
       
   671 
       
   672 void
       
   673 QKeyMapperPrivate::clearMappings()
       
   674 {
       
   675     deleteLayouts();
       
   676     updateKeyboard();
       
   677 }
       
   678 
       
   679 QList<int>
       
   680 QKeyMapperPrivate::possibleKeys(QKeyEvent *e)
       
   681 {
       
   682     QList<int> ret;
       
   683 
       
   684     KeyboardLayoutItem *kbItem = keyLayout[e->nativeVirtualKey()];
       
   685     if (!kbItem) // Key is not in any keyboard layout (e.g. eisu-key on Japanese keyboard) 
       
   686         return ret;
       
   687 
       
   688     int baseKey = kbItem->qtKey[0];
       
   689     Qt::KeyboardModifiers keyMods = e->modifiers();
       
   690     ret << int(baseKey + keyMods); // The base key is _always_ valid, of course
       
   691 
       
   692     for (int i = 1; i < 8; ++i) {
       
   693         Qt::KeyboardModifiers neededMods = ModsTbl[i];
       
   694         int key = kbItem->qtKey[i];
       
   695         if (key && key != baseKey && ((keyMods & neededMods) == neededMods))
       
   696             ret << int(key + (keyMods & ~neededMods));
       
   697     }
       
   698 
       
   699     return ret;
       
   700 }
       
   701 
       
   702 bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, EventHandlerCallRef er, EventRef event,
       
   703                                           void *info, bool grab)
       
   704 {
       
   705     Q_ASSERT(GetEventClass(event) == kEventClassKeyboard);
       
   706     bool handled_event=true;
       
   707     UInt32 ekind = GetEventKind(event);
       
   708 
       
   709     // unfortunately modifiers changed event looks quite different, so I have a separate
       
   710     // code path
       
   711     if (ekind == kEventRawKeyModifiersChanged) {
       
   712         //figure out changed modifiers, wish Apple would just send a delta
       
   713         UInt32 modifiers = 0;
       
   714         GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, 0,
       
   715                           sizeof(modifiers), 0, &modifiers);
       
   716         qt_mac_send_modifiers_changed(modifiers, widget);
       
   717         return true;
       
   718     }
       
   719 
       
   720     if (qApp->inputContext() && qApp->inputContext()->isComposing()) {
       
   721         if (ekind == kEventRawKeyDown) {
       
   722             QMacInputContext *context = qobject_cast<QMacInputContext*>(qApp->inputContext());
       
   723             if (context)
       
   724                 context->setLastKeydownEvent(event);
       
   725         }
       
   726         return false;
       
   727     }
       
   728     //get modifiers
       
   729     Qt::KeyboardModifiers modifiers;
       
   730     int qtKey;
       
   731     QChar ourChar;
       
   732     if (translateKeyEventInternal(er, event, &qtKey, &ourChar, &modifiers,
       
   733                                   &handled_event) == false)
       
   734         return handled_event;
       
   735     QString text(ourChar);
       
   736     /* This is actually wrong - but unfortunatly it is the best that can be
       
   737        done for now because of the Control/Meta mapping problems */
       
   738     if (modifiers & (Qt::ControlModifier | Qt::MetaModifier)
       
   739         && !qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
       
   740         text = QString();
       
   741     }
       
   742 
       
   743 
       
   744     if (widget) {
       
   745 #ifndef QT_MAC_USE_COCOA
       
   746         Q_UNUSED(info);
       
   747         // Try not to call "other" event handlers if we have a popup,
       
   748         // However, if the key has text
       
   749         // then we should pass it along because otherwise then people
       
   750         // can use input method stuff.
       
   751         if (!qApp->activePopupWidget()
       
   752                 || (qApp->activePopupWidget() && !text.isEmpty())) {
       
   753             //Find out if someone else wants the event, namely
       
   754             //is it of use to text services? If so we won't bother
       
   755             //with a QKeyEvent.
       
   756             qt_mac_eat_unicode_key = false;
       
   757             if (er)
       
   758                 CallNextEventHandler(er, event);
       
   759             extern bool qt_mac_menubar_is_open();   
       
   760             if (qt_mac_eat_unicode_key || qt_mac_menubar_is_open()) {
       
   761                 return true;
       
   762             }
       
   763         }
       
   764 #endif
       
   765         // Try to compress key events.
       
   766         if (!text.isEmpty() && widget->testAttribute(Qt::WA_KeyCompression)) {
       
   767             EventTime lastTime = GetEventTime(event);
       
   768             for (;;) {
       
   769                 EventRef releaseEvent = FindSpecificEventInQueue(GetMainEventQueue(),
       
   770                                                                  qt_KeyEventComparatorProc,
       
   771                                                                  (void*)kEventRawKeyUp);
       
   772                 if (!releaseEvent)
       
   773                     break;
       
   774                 const EventTime releaseTime = GetEventTime(releaseEvent);
       
   775                 if (releaseTime < lastTime)
       
   776                     break;
       
   777                 lastTime = releaseTime;
       
   778 
       
   779                 EventRef pressEvent = FindSpecificEventInQueue(GetMainEventQueue(),
       
   780                                                                qt_KeyEventComparatorProc,
       
   781                                                                (void*)kEventRawKeyDown);
       
   782                 if (!pressEvent)
       
   783                     break;
       
   784                 const EventTime pressTime = GetEventTime(pressEvent);
       
   785                 if (pressTime < lastTime)
       
   786                     break;
       
   787                 lastTime = pressTime;
       
   788 
       
   789                 Qt::KeyboardModifiers compressMod;
       
   790                 int compressQtKey = 0;
       
   791                 QChar compressChar;
       
   792                 if (translateKeyEventInternal(er, pressEvent,
       
   793                                               &compressQtKey, &compressChar, &compressMod, 0)
       
   794                     == false) {
       
   795                     break;
       
   796                 }
       
   797                 // Copied from qapplication_x11.cpp (change both).
       
   798 
       
   799                 bool stopCompression =
       
   800                     // 1) misc keys
       
   801                     (compressQtKey >= Qt::Key_Escape && compressQtKey <= Qt::Key_SysReq)
       
   802                     // 2) cursor movement
       
   803                     || (compressQtKey >= Qt::Key_Home && compressQtKey <= Qt::Key_PageDown)
       
   804                     // 3) extra keys
       
   805                     || (compressQtKey >= Qt::Key_Super_L && compressQtKey <= Qt::Key_Direction_R)
       
   806                     // 4) something that a) doesn't translate to text or b) translates
       
   807                     //    to newline text
       
   808                     || (compressQtKey == 0)
       
   809                     || (compressChar == QLatin1Char('\n'))
       
   810                     || (compressQtKey == Qt::Key_unknown);
       
   811 
       
   812                 if (compressMod == modifiers && !compressChar.isNull() && !stopCompression) {
       
   813 #ifdef DEBUG_KEY_BINDINGS
       
   814                     qDebug("compressing away %c", compressChar.toLatin1());
       
   815 #endif
       
   816                     text += compressChar;
       
   817                     // Clean up
       
   818                     RemoveEventFromQueue(GetMainEventQueue(), releaseEvent);
       
   819                     RemoveEventFromQueue(GetMainEventQueue(), pressEvent);
       
   820                 } else {
       
   821 #ifdef DEBUG_KEY_BINDINGS
       
   822                     qDebug("stoping compression..");
       
   823 #endif
       
   824                     break;
       
   825                 }
       
   826             }
       
   827         }
       
   828 
       
   829         // There is no way to get the scan code from carbon. But we cannot use the value 0, since
       
   830         // it indicates that the event originates from somewhere else than the keyboard
       
   831         UInt32 macScanCode = 1;
       
   832         UInt32 macVirtualKey = 0;
       
   833         GetEventParameter(event, kEventParamKeyCode, typeUInt32, 0, sizeof(macVirtualKey), 0, &macVirtualKey);
       
   834         UInt32 macModifiers = 0;
       
   835         GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, 0,
       
   836                           sizeof(macModifiers), 0, &macModifiers);
       
   837         handled_event = QKeyMapper::sendKeyEvent(widget, grab,
       
   838                                                  (ekind == kEventRawKeyUp) ? QEvent::KeyRelease : QEvent::KeyPress,
       
   839                                                  qtKey, modifiers, text, ekind == kEventRawKeyRepeat, 0,
       
   840                                                  macScanCode, macVirtualKey, macModifiers
       
   841 #ifdef QT_MAC_USE_COCOA
       
   842                                                  ,static_cast<bool *>(info)
       
   843 #endif
       
   844                                                  );
       
   845     }
       
   846     return handled_event;
       
   847 }
       
   848 
       
   849 void
       
   850 QKeyMapperPrivate::updateKeyMap(EventHandlerCallRef, EventRef event, void *)
       
   851 {
       
   852     UInt32 macVirtualKey = 0;
       
   853     GetEventParameter(event, kEventParamKeyCode, typeUInt32, 0, sizeof(macVirtualKey), 0, &macVirtualKey);
       
   854     if (updateKeyboard())
       
   855        QKeyMapper::changeKeyboard();
       
   856     else if (keyLayout[macVirtualKey])
       
   857         return;
       
   858 
       
   859     UniCharCount buffer_size = 10;
       
   860     UniChar buffer[buffer_size];
       
   861     keyLayout[macVirtualKey] = new KeyboardLayoutItem;
       
   862     for (int i = 0; i < 16; ++i) {
       
   863         UniCharCount out_buffer_size = 0;
       
   864         keyLayout[macVirtualKey]->qtKey[i] = 0;
       
   865 #ifdef Q_WS_MAC32
       
   866         if (keyboard_mode == UnicodeMode) {
       
   867 #endif
       
   868             const UInt32 keyModifier = ((qt_mac_get_mac_modifiers(ModsTbl[i]) >> 8) & 0xFF);
       
   869             OSStatus err = UCKeyTranslate(keyboard_layout_format.unicode, macVirtualKey, kUCKeyActionDown, keyModifier,
       
   870                                           keyboard_kind, 0, &keyboard_dead, buffer_size, &out_buffer_size, buffer);
       
   871             if (err == noErr && out_buffer_size) {
       
   872                 const QChar unicode(buffer[0]);
       
   873                 int qtkey = qt_mac_get_key(keyModifier, unicode, macVirtualKey);
       
   874                 if (qtkey == Qt::Key_unknown)
       
   875                     qtkey = unicode.unicode();
       
   876                 keyLayout[macVirtualKey]->qtKey[i] = qtkey;
       
   877             }
       
   878 #ifdef Q_WS_MAC32            
       
   879         } else {
       
   880             const UInt32 keyModifier = (qt_mac_get_mac_modifiers(ModsTbl[i]));
       
   881 
       
   882             uchar translatedChar = KeyTranslate(keyboard_layout_format.other, keyModifier | macVirtualKey, &keyboard_dead);
       
   883             if (translatedChar) {
       
   884                 static QTextCodec *c = 0;
       
   885                 if (!c)
       
   886                     c = QTextCodec::codecForName("Apple Roman");
       
   887                 const QChar unicode(c->toUnicode((const char *)&translatedChar, 1).at(0));
       
   888                 int qtkey = qt_mac_get_key(keyModifier, unicode, macVirtualKey);
       
   889                 if (qtkey == Qt::Key_unknown)
       
   890                     qtkey = unicode.unicode();
       
   891                 keyLayout[macVirtualKey]->qtKey[i] = qtkey;
       
   892             }
       
   893         }
       
   894 #endif
       
   895     }
       
   896 #ifdef DEBUG_KEY_MAPS
       
   897     qDebug("updateKeyMap for virtual key = 0x%02x!", (uint)macVirtualKey);
       
   898     for (int i = 0; i < 16; ++i) {
       
   899         qDebug("    [%d] (%d,0x%02x,'%c')", i,
       
   900                keyLayout[macVirtualKey]->qtKey[i],
       
   901                keyLayout[macVirtualKey]->qtKey[i],
       
   902                keyLayout[macVirtualKey]->qtKey[i]);
       
   903     }
       
   904 #endif
       
   905 }
       
   906 
       
   907 bool
       
   908 QKeyMapper::sendKeyEvent(QWidget *widget, bool grab,
       
   909                          QEvent::Type type, int code, Qt::KeyboardModifiers modifiers,
       
   910                          const QString &text, bool autorepeat, int count,
       
   911                          quint32 nativeScanCode, quint32 nativeVirtualKey,
       
   912                          quint32 nativeModifiers, bool *isAccepted)
       
   913 {
       
   914     Q_UNUSED(count);
       
   915     if (widget && widget->isEnabled()) {
       
   916         bool key_event = true;
       
   917 #if defined(QT3_SUPPORT) && !defined(QT_NO_SHORTCUT)
       
   918         if (type == QEvent::KeyPress && !grab
       
   919            && QApplicationPrivate::instance()->use_compat()) {
       
   920                QKeyEventEx accel_ev(type, code, modifiers,
       
   921                                     text, autorepeat, qMax(1, int(text.length())),
       
   922                                     nativeScanCode, nativeVirtualKey, nativeModifiers);
       
   923             if (QApplicationPrivate::instance()->qt_tryAccelEvent(widget, &accel_ev)) {
       
   924 #if defined(DEBUG_KEY_BINDINGS) || defined(DEBUG_KEY_BINDINGS_MODIFIERS)
       
   925                 qDebug("KeyEvent: %s::%s consumed Accel: %s",
       
   926                        widget ? widget->metaObject()->className() : "none",
       
   927                        widget ? widget->objectName().toLatin1().constData() : "",
       
   928                        text.toLatin1().constData());
       
   929 #endif
       
   930                 key_event = false;
       
   931             } else {
       
   932                 if (accel_ev.isAccepted()) {
       
   933 #if defined(DEBUG_KEY_BINDINGS) || defined(DEBUG_KEY_BINDINGS_MODIFIERS)
       
   934                     qDebug("KeyEvent: %s::%s overrode Accel: %s",
       
   935                            widget ? widget->metaObject()->className() : "none",
       
   936                            widget ? widget->objectName().toLatin1().constData() : "",
       
   937                            text.toLatin1().constData());
       
   938 #endif
       
   939                 }
       
   940             }
       
   941         }
       
   942 #else
       
   943 Q_UNUSED(grab);
       
   944 #endif // QT3_SUPPORT && !QT_NO_SHORTCUT
       
   945         if (key_event) {
       
   946 #if defined(DEBUG_KEY_BINDINGS) || defined(DEBUG_KEY_BINDINGS_MODIFIERS)
       
   947             qDebug("KeyEvent: Sending %s to %s::%s: %s 0x%08x%s",
       
   948                    type == QEvent::KeyRelease ? "KeyRelease" : "KeyPress",
       
   949                    widget ? widget->metaObject()->className() : "none",
       
   950                    widget ? widget->objectName().toLatin1().constData() : "",
       
   951                    text.toLatin1().constData(), int(modifiers),
       
   952                    autorepeat ? " Repeat" : "");
       
   953 #endif
       
   954             QKeyEventEx ke(type, code, modifiers, text, autorepeat, qMax(1, text.length()),
       
   955                            nativeScanCode, nativeVirtualKey, nativeModifiers);
       
   956             bool retMe = qt_sendSpontaneousEvent(widget,&ke);
       
   957             if (isAccepted)
       
   958                 *isAccepted = ke.isAccepted();
       
   959             return retMe;
       
   960         }
       
   961     }
       
   962     return false;
       
   963 }
       
   964 
       
   965 QT_END_NAMESPACE