1/**************************************************************************** 2** 3** Copyright (C) 2016 The Qt Company Ltd. 4** Contact: https://www.qt.io/licensing/ 5** 6** This file is part of the plugins of the Qt Toolkit. 7** 8** $QT_BEGIN_LICENSE:LGPL$ 9** Commercial License Usage 10** Licensees holding valid commercial Qt licenses may use this file in 11** accordance with the commercial license agreement provided with the 12** Software or, alternatively, in accordance with the terms contained in 13** a written agreement between you and The Qt Company. For licensing terms 14** and conditions see https://www.qt.io/terms-conditions. For further 15** information use the contact form at https://www.qt.io/contact-us. 16** 17** GNU Lesser General Public License Usage 18** Alternatively, this file may be used under the terms of the GNU Lesser 19** General Public License version 3 as published by the Free Software 20** Foundation and appearing in the file LICENSE.LGPL3 included in the 21** packaging of this file. Please review the following information to 22** ensure the GNU Lesser General Public License version 3 requirements 23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 24** 25** GNU General Public License Usage 26** Alternatively, this file may be used under the terms of the GNU 27** General Public License version 2.0 or (at your option) the GNU General 28** Public license version 3 or any later version approved by the KDE Free 29** Qt Foundation. The licenses are as published by the Free Software 30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 31** included in the packaging of this file. Please review the following 32** information to ensure the GNU General Public License requirements will 33** be met: https://www.gnu.org/licenses/gpl-2.0.html and 34** https://www.gnu.org/licenses/gpl-3.0.html. 35** 36** $QT_END_LICENSE$ 37** 38****************************************************************************/ 39 40#include "qcocoakeymapper.h" 41 42#include <QtCore/QDebug> 43#include <QtGui/QGuiApplication> 44 45QT_BEGIN_NAMESPACE 46 47// QCocoaKeyMapper debug facilities 48//#define DEBUG_KEY_BINDINGS 49//#define DEBUG_KEY_BINDINGS_MODIFIERS 50//#define DEBUG_KEY_MAPS 51 52// Possible modifier states. 53// NOTE: The order of these states match the order in updatePossibleKeyCodes()! 54static const Qt::KeyboardModifiers ModsTbl[] = { 55 Qt::NoModifier, // 0 56 Qt::ShiftModifier, // 1 57 Qt::ControlModifier, // 2 58 Qt::ControlModifier | Qt::ShiftModifier, // 3 59 Qt::AltModifier, // 4 60 Qt::AltModifier | Qt::ShiftModifier, // 5 61 Qt::AltModifier | Qt::ControlModifier, // 6 62 Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7 63 Qt::MetaModifier, // 8 64 Qt::MetaModifier | Qt::ShiftModifier, // 9 65 Qt::MetaModifier | Qt::ControlModifier, // 10 66 Qt::MetaModifier | Qt::ControlModifier | Qt::ShiftModifier,// 11 67 Qt::MetaModifier | Qt::AltModifier, // 12 68 Qt::MetaModifier | Qt::AltModifier | Qt::ShiftModifier, // 13 69 Qt::MetaModifier | Qt::AltModifier | Qt::ControlModifier, // 14 70 Qt::MetaModifier | Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 15 71}; 72 73bool qt_mac_eat_unicode_key = false; 74 75 76/* key maps */ 77struct qt_mac_enum_mapper 78{ 79 int mac_code; 80 int qt_code; 81#if defined(DEBUG_KEY_BINDINGS) 82# define QT_MAC_MAP_ENUM(x) x, #x 83 const char *desc; 84#else 85# define QT_MAC_MAP_ENUM(x) x 86#endif 87}; 88 89//modifiers 90static qt_mac_enum_mapper qt_mac_modifier_symbols[] = { 91 { shiftKey, QT_MAC_MAP_ENUM(Qt::ShiftModifier) }, 92 { rightShiftKey, QT_MAC_MAP_ENUM(Qt::ShiftModifier) }, 93 { controlKey, QT_MAC_MAP_ENUM(Qt::MetaModifier) }, 94 { rightControlKey, QT_MAC_MAP_ENUM(Qt::MetaModifier) }, 95 { cmdKey, QT_MAC_MAP_ENUM(Qt::ControlModifier) }, 96 { optionKey, QT_MAC_MAP_ENUM(Qt::AltModifier) }, 97 { rightOptionKey, QT_MAC_MAP_ENUM(Qt::AltModifier) }, 98 { kEventKeyModifierNumLockMask, QT_MAC_MAP_ENUM(Qt::KeypadModifier) }, 99 { 0, QT_MAC_MAP_ENUM(0) } 100}; 101Qt::KeyboardModifiers qt_mac_get_modifiers(int keys) 102{ 103#ifdef DEBUG_KEY_BINDINGS_MODIFIERS 104 qDebug("Qt: internal: **Mapping modifiers: %d (0x%04x)", keys, keys); 105#endif 106 Qt::KeyboardModifiers ret = Qt::NoModifier; 107 for (int i = 0; qt_mac_modifier_symbols[i].qt_code; i++) { 108 if (keys & qt_mac_modifier_symbols[i].mac_code) { 109#ifdef DEBUG_KEY_BINDINGS_MODIFIERS 110 qDebug("Qt: internal: got modifier: %s", qt_mac_modifier_symbols[i].desc); 111#endif 112 ret |= Qt::KeyboardModifier(qt_mac_modifier_symbols[i].qt_code); 113 } 114 } 115 if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { 116 Qt::KeyboardModifiers oldModifiers = ret; 117 ret &= ~(Qt::MetaModifier | Qt::ControlModifier); 118 if (oldModifiers & Qt::ControlModifier) 119 ret |= Qt::MetaModifier; 120 if (oldModifiers & Qt::MetaModifier) 121 ret |= Qt::ControlModifier; 122 } 123 return ret; 124} 125static int qt_mac_get_mac_modifiers(Qt::KeyboardModifiers keys) 126{ 127#ifdef DEBUG_KEY_BINDINGS_MODIFIERS 128 qDebug("Qt: internal: **Mapping modifiers: %d (0x%04x)", (int)keys, (int)keys); 129#endif 130 int ret = 0; 131 for (int i = 0; qt_mac_modifier_symbols[i].qt_code; i++) { 132 if (keys & qt_mac_modifier_symbols[i].qt_code) { 133#ifdef DEBUG_KEY_BINDINGS_MODIFIERS 134 qDebug("Qt: internal: got modifier: %s", qt_mac_modifier_symbols[i].desc); 135#endif 136 ret |= qt_mac_modifier_symbols[i].mac_code; 137 } 138 } 139 140 if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { 141 int oldModifiers = ret; 142 ret &= ~(controlKeyBit | cmdKeyBit); 143 if (oldModifiers & controlKeyBit) 144 ret |= cmdKeyBit; 145 if (oldModifiers & cmdKeyBit) 146 ret |= controlKeyBit; 147 } 148 return ret; 149} 150 151//keyboard keys (non-modifiers) 152static qt_mac_enum_mapper qt_mac_keyboard_symbols[] = { 153 { kHomeCharCode, QT_MAC_MAP_ENUM(Qt::Key_Home) }, 154 { kEnterCharCode, QT_MAC_MAP_ENUM(Qt::Key_Enter) }, 155 { kEndCharCode, QT_MAC_MAP_ENUM(Qt::Key_End) }, 156 { kBackspaceCharCode, QT_MAC_MAP_ENUM(Qt::Key_Backspace) }, 157 { kTabCharCode, QT_MAC_MAP_ENUM(Qt::Key_Tab) }, 158 { kPageUpCharCode, QT_MAC_MAP_ENUM(Qt::Key_PageUp) }, 159 { kPageDownCharCode, QT_MAC_MAP_ENUM(Qt::Key_PageDown) }, 160 { kReturnCharCode, QT_MAC_MAP_ENUM(Qt::Key_Return) }, 161 { kEscapeCharCode, QT_MAC_MAP_ENUM(Qt::Key_Escape) }, 162 { kLeftArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Left) }, 163 { kRightArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Right) }, 164 { kUpArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Up) }, 165 { kDownArrowCharCode, QT_MAC_MAP_ENUM(Qt::Key_Down) }, 166 { kHelpCharCode, QT_MAC_MAP_ENUM(Qt::Key_Help) }, 167 { kDeleteCharCode, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, 168//ascii maps, for debug 169 { ':', QT_MAC_MAP_ENUM(Qt::Key_Colon) }, 170 { ';', QT_MAC_MAP_ENUM(Qt::Key_Semicolon) }, 171 { '<', QT_MAC_MAP_ENUM(Qt::Key_Less) }, 172 { '=', QT_MAC_MAP_ENUM(Qt::Key_Equal) }, 173 { '>', QT_MAC_MAP_ENUM(Qt::Key_Greater) }, 174 { '?', QT_MAC_MAP_ENUM(Qt::Key_Question) }, 175 { '@', QT_MAC_MAP_ENUM(Qt::Key_At) }, 176 { ' ', QT_MAC_MAP_ENUM(Qt::Key_Space) }, 177 { '!', QT_MAC_MAP_ENUM(Qt::Key_Exclam) }, 178 { '"', QT_MAC_MAP_ENUM(Qt::Key_QuoteDbl) }, 179 { '#', QT_MAC_MAP_ENUM(Qt::Key_NumberSign) }, 180 { '$', QT_MAC_MAP_ENUM(Qt::Key_Dollar) }, 181 { '%', QT_MAC_MAP_ENUM(Qt::Key_Percent) }, 182 { '&', QT_MAC_MAP_ENUM(Qt::Key_Ampersand) }, 183 { '\'', QT_MAC_MAP_ENUM(Qt::Key_Apostrophe) }, 184 { '(', QT_MAC_MAP_ENUM(Qt::Key_ParenLeft) }, 185 { ')', QT_MAC_MAP_ENUM(Qt::Key_ParenRight) }, 186 { '*', QT_MAC_MAP_ENUM(Qt::Key_Asterisk) }, 187 { '+', QT_MAC_MAP_ENUM(Qt::Key_Plus) }, 188 { ',', QT_MAC_MAP_ENUM(Qt::Key_Comma) }, 189 { '-', QT_MAC_MAP_ENUM(Qt::Key_Minus) }, 190 { '.', QT_MAC_MAP_ENUM(Qt::Key_Period) }, 191 { '/', QT_MAC_MAP_ENUM(Qt::Key_Slash) }, 192 { '[', QT_MAC_MAP_ENUM(Qt::Key_BracketLeft) }, 193 { ']', QT_MAC_MAP_ENUM(Qt::Key_BracketRight) }, 194 { '\\', QT_MAC_MAP_ENUM(Qt::Key_Backslash) }, 195 { '_', QT_MAC_MAP_ENUM(Qt::Key_Underscore) }, 196 { '`', QT_MAC_MAP_ENUM(Qt::Key_QuoteLeft) }, 197 { '{', QT_MAC_MAP_ENUM(Qt::Key_BraceLeft) }, 198 { '}', QT_MAC_MAP_ENUM(Qt::Key_BraceRight) }, 199 { '|', QT_MAC_MAP_ENUM(Qt::Key_Bar) }, 200 { '~', QT_MAC_MAP_ENUM(Qt::Key_AsciiTilde) }, 201 { '^', QT_MAC_MAP_ENUM(Qt::Key_AsciiCircum) }, 202 { 0, QT_MAC_MAP_ENUM(0) } 203}; 204 205static qt_mac_enum_mapper qt_mac_keyvkey_symbols[] = { //real scan codes 206 { kVK_F1, QT_MAC_MAP_ENUM(Qt::Key_F1) }, 207 { kVK_F2, QT_MAC_MAP_ENUM(Qt::Key_F2) }, 208 { kVK_F3, QT_MAC_MAP_ENUM(Qt::Key_F3) }, 209 { kVK_F4, QT_MAC_MAP_ENUM(Qt::Key_F4) }, 210 { kVK_F5, QT_MAC_MAP_ENUM(Qt::Key_F5) }, 211 { kVK_F6, QT_MAC_MAP_ENUM(Qt::Key_F6) }, 212 { kVK_F7, QT_MAC_MAP_ENUM(Qt::Key_F7) }, 213 { kVK_F8, QT_MAC_MAP_ENUM(Qt::Key_F8) }, 214 { kVK_F9, QT_MAC_MAP_ENUM(Qt::Key_F9) }, 215 { kVK_F10, QT_MAC_MAP_ENUM(Qt::Key_F10) }, 216 { kVK_F11, QT_MAC_MAP_ENUM(Qt::Key_F11) }, 217 { kVK_F12, QT_MAC_MAP_ENUM(Qt::Key_F12) }, 218 { kVK_F13, QT_MAC_MAP_ENUM(Qt::Key_F13) }, 219 { kVK_F14, QT_MAC_MAP_ENUM(Qt::Key_F14) }, 220 { kVK_F15, QT_MAC_MAP_ENUM(Qt::Key_F15) }, 221 { kVK_F16, QT_MAC_MAP_ENUM(Qt::Key_F16) }, 222 { kVK_Return, QT_MAC_MAP_ENUM(Qt::Key_Return) }, 223 { kVK_Tab, QT_MAC_MAP_ENUM(Qt::Key_Tab) }, 224 { kVK_Escape, QT_MAC_MAP_ENUM(Qt::Key_Escape) }, 225 { kVK_Help, QT_MAC_MAP_ENUM(Qt::Key_Help) }, 226 { kVK_UpArrow, QT_MAC_MAP_ENUM(Qt::Key_Up) }, 227 { kVK_DownArrow, QT_MAC_MAP_ENUM(Qt::Key_Down) }, 228 { kVK_LeftArrow, QT_MAC_MAP_ENUM(Qt::Key_Left) }, 229 { kVK_RightArrow, QT_MAC_MAP_ENUM(Qt::Key_Right) }, 230 { kVK_PageUp, QT_MAC_MAP_ENUM(Qt::Key_PageUp) }, 231 { kVK_PageDown, QT_MAC_MAP_ENUM(Qt::Key_PageDown) }, 232 { 0, QT_MAC_MAP_ENUM(0) } 233}; 234 235static qt_mac_enum_mapper qt_mac_private_unicode[] = { 236 { 0xF700, QT_MAC_MAP_ENUM(Qt::Key_Up) }, //NSUpArrowFunctionKey 237 { 0xF701, QT_MAC_MAP_ENUM(Qt::Key_Down) }, //NSDownArrowFunctionKey 238 { 0xF702, QT_MAC_MAP_ENUM(Qt::Key_Left) }, //NSLeftArrowFunctionKey 239 { 0xF703, QT_MAC_MAP_ENUM(Qt::Key_Right) }, //NSRightArrowFunctionKey 240 { 0xF727, QT_MAC_MAP_ENUM(Qt::Key_Insert) }, //NSInsertFunctionKey 241 { 0xF728, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, //NSDeleteFunctionKey 242 { 0xF729, QT_MAC_MAP_ENUM(Qt::Key_Home) }, //NSHomeFunctionKey 243 { 0xF72B, QT_MAC_MAP_ENUM(Qt::Key_End) }, //NSEndFunctionKey 244 { 0xF72C, QT_MAC_MAP_ENUM(Qt::Key_PageUp) }, //NSPageUpFunctionKey 245 { 0xF72D, QT_MAC_MAP_ENUM(Qt::Key_PageDown) }, //NSPageDownFunctionKey 246 { 0xF72E, QT_MAC_MAP_ENUM(Qt::Key_Print) }, //NSPrintScreenFunctionKey 247 { 0xF72F, QT_MAC_MAP_ENUM(Qt::Key_ScrollLock) }, //NSScrollLockFunctionKey 248 { 0xF730, QT_MAC_MAP_ENUM(Qt::Key_Pause) }, //NSPauseFunctionKey 249 { 0xF731, QT_MAC_MAP_ENUM(Qt::Key_SysReq) }, //NSSysReqFunctionKey 250 { 0xF735, QT_MAC_MAP_ENUM(Qt::Key_Menu) }, //NSMenuFunctionKey 251 { 0xF738, QT_MAC_MAP_ENUM(Qt::Key_Printer) }, //NSPrintFunctionKey 252 { 0xF73A, QT_MAC_MAP_ENUM(Qt::Key_Clear) }, //NSClearDisplayFunctionKey 253 { 0xF73D, QT_MAC_MAP_ENUM(Qt::Key_Insert) }, //NSInsertCharFunctionKey 254 { 0xF73E, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, //NSDeleteCharFunctionKey 255 { 0xF741, QT_MAC_MAP_ENUM(Qt::Key_Select) }, //NSSelectFunctionKey 256 { 0xF742, QT_MAC_MAP_ENUM(Qt::Key_Execute) }, //NSExecuteFunctionKey 257 { 0xF743, QT_MAC_MAP_ENUM(Qt::Key_Undo) }, //NSUndoFunctionKey 258 { 0xF744, QT_MAC_MAP_ENUM(Qt::Key_Redo) }, //NSRedoFunctionKey 259 { 0xF745, QT_MAC_MAP_ENUM(Qt::Key_Find) }, //NSFindFunctionKey 260 { 0xF746, QT_MAC_MAP_ENUM(Qt::Key_Help) }, //NSHelpFunctionKey 261 { 0xF747, QT_MAC_MAP_ENUM(Qt::Key_Mode_switch) }, //NSModeSwitchFunctionKey 262 { 0, QT_MAC_MAP_ENUM(0) } 263}; 264 265static int qt_mac_get_key(int modif, const QChar &key, int virtualKey) 266{ 267#ifdef DEBUG_KEY_BINDINGS 268 qDebug("**Mapping key: %d (0x%04x) - %d (0x%04x)", key.unicode(), key.unicode(), virtualKey, virtualKey); 269#endif 270 271 if (key == kClearCharCode && virtualKey == 0x47) 272 return Qt::Key_Clear; 273 274 if (key.isDigit()) { 275#ifdef DEBUG_KEY_BINDINGS 276 qDebug("%d: got key: %d", __LINE__, key.digitValue()); 277#endif 278 return key.digitValue() + Qt::Key_0; 279 } 280 281 if (key.isLetter()) { 282#ifdef DEBUG_KEY_BINDINGS 283 qDebug("%d: got key: %d", __LINE__, (key.toUpper().unicode() - 'A')); 284#endif 285 return (key.toUpper().unicode() - 'A') + Qt::Key_A; 286 } 287 if (key.isSymbol()) { 288#ifdef DEBUG_KEY_BINDINGS 289 qDebug("%d: got key: %d", __LINE__, (key.unicode())); 290#endif 291 return key.unicode(); 292 } 293 294 for (int i = 0; qt_mac_keyboard_symbols[i].qt_code; i++) { 295 if (qt_mac_keyboard_symbols[i].mac_code == key) { 296 /* To work like Qt for X11 we issue Backtab when Shift + Tab are pressed */ 297 if (qt_mac_keyboard_symbols[i].qt_code == Qt::Key_Tab && (modif & Qt::ShiftModifier)) { 298#ifdef DEBUG_KEY_BINDINGS 299 qDebug("%d: got key: Qt::Key_Backtab", __LINE__); 300#endif 301 return Qt::Key_Backtab; 302 } 303 304#ifdef DEBUG_KEY_BINDINGS 305 qDebug("%d: got key: %s", __LINE__, qt_mac_keyboard_symbols[i].desc); 306#endif 307 return qt_mac_keyboard_symbols[i].qt_code; 308 } 309 } 310 311 //last ditch try to match the scan code 312 for (int i = 0; qt_mac_keyvkey_symbols[i].qt_code; i++) { 313 if (qt_mac_keyvkey_symbols[i].mac_code == virtualKey) { 314#ifdef DEBUG_KEY_BINDINGS 315 qDebug("%d: got key: %s", __LINE__, qt_mac_keyvkey_symbols[i].desc); 316#endif 317 return qt_mac_keyvkey_symbols[i].qt_code; 318 } 319 } 320 321 // check if they belong to key codes in private unicode range 322 if (key >= 0xf700 && key <= 0xf747) { 323 if (key >= 0xf704 && key <= 0xf726) { 324 return Qt::Key_F1 + (key.unicode() - 0xf704) ; 325 } 326 for (int i = 0; qt_mac_private_unicode[i].qt_code; i++) { 327 if (qt_mac_private_unicode[i].mac_code == key) { 328 return qt_mac_private_unicode[i].qt_code; 329 } 330 } 331 332 } 333 334 //oh well 335#ifdef DEBUG_KEY_BINDINGS 336 qDebug("Unknown case.. %s:%d %d[%d] %d", __FILE__, __LINE__, key.unicode(), key.toLatin1(), virtualKey); 337#endif 338 return Qt::Key_unknown; 339} 340 341QCocoaKeyMapper::QCocoaKeyMapper() 342{ 343 memset(keyLayout, 0, sizeof(keyLayout)); 344} 345 346QCocoaKeyMapper::~QCocoaKeyMapper() 347{ 348 deleteLayouts(); 349} 350 351Qt::KeyboardModifiers QCocoaKeyMapper::queryKeyboardModifiers() 352{ 353 return qt_mac_get_modifiers(GetCurrentKeyModifiers()); 354} 355 356bool QCocoaKeyMapper::updateKeyboard() 357{ 358 const UCKeyboardLayout *uchrData = nullptr; 359 QCFType<TISInputSourceRef> source = TISCopyInputMethodKeyboardLayoutOverride(); 360 if (!source) 361 source = TISCopyCurrentKeyboardInputSource(); 362 if (keyboard_mode != NullMode && source == currentInputSource) { 363 return false; 364 } 365 Q_ASSERT(source); 366 CFDataRef data = static_cast<CFDataRef>(TISGetInputSourceProperty(source, 367 kTISPropertyUnicodeKeyLayoutData)); 368 uchrData = data ? reinterpret_cast<const UCKeyboardLayout *>(CFDataGetBytePtr(data)) : nullptr; 369 370 keyboard_kind = LMGetKbdType(); 371 if (uchrData) { 372 keyboard_layout_format = uchrData; 373 keyboard_mode = UnicodeMode; 374 } else { 375 keyboard_layout_format = nullptr; 376 keyboard_mode = NullMode; 377 } 378 currentInputSource = source; 379 keyboard_dead = 0; 380 381 const auto newMode = keyboard_mode; 382 deleteLayouts(); 383 keyboard_mode = newMode; 384 385 return true; 386} 387 388void QCocoaKeyMapper::deleteLayouts() 389{ 390 keyboard_mode = NullMode; 391 for (int i = 0; i < 255; ++i) { 392 if (keyLayout[i]) { 393 delete keyLayout[i]; 394 keyLayout[i] = nullptr; 395 } 396 } 397} 398 399void QCocoaKeyMapper::clearMappings() 400{ 401 deleteLayouts(); 402 updateKeyboard(); 403} 404 405void QCocoaKeyMapper::updateKeyMap(unsigned short macVirtualKey, QChar unicodeKey) 406{ 407 updateKeyboard(); 408 409 if (keyLayout[macVirtualKey]) 410 return; 411 412 UniCharCount buffer_size = 10; 413 UniChar buffer[buffer_size]; 414 keyLayout[macVirtualKey] = new KeyboardLayoutItem; 415 for (int i = 0; i < 16; ++i) { 416 UniCharCount out_buffer_size = 0; 417 keyLayout[macVirtualKey]->qtKey[i] = 0; 418 419 const UInt32 keyModifier = ((qt_mac_get_mac_modifiers(ModsTbl[i]) >> 8) & 0xFF); 420 OSStatus err = UCKeyTranslate(keyboard_layout_format, macVirtualKey, kUCKeyActionDown, keyModifier, 421 keyboard_kind, 0, &keyboard_dead, buffer_size, &out_buffer_size, buffer); 422 if (err == noErr && out_buffer_size) { 423 const QChar unicode(buffer[0]); 424 int qtkey = qt_mac_get_key(keyModifier, unicode, macVirtualKey); 425 if (qtkey == Qt::Key_unknown) 426 qtkey = unicode.unicode(); 427 keyLayout[macVirtualKey]->qtKey[i] = qtkey; 428 } else { 429 int qtkey = qt_mac_get_key(keyModifier, unicodeKey, macVirtualKey); 430 if (qtkey == Qt::Key_unknown) 431 qtkey = unicodeKey.unicode(); 432 keyLayout[macVirtualKey]->qtKey[i] = qtkey; 433 } 434 } 435#ifdef DEBUG_KEY_MAPS 436 qDebug("updateKeyMap for virtual key = 0x%02x!", (uint)macVirtualKey); 437 for (int i = 0; i < 16; ++i) { 438 qDebug(" [%d] (%d,0x%02x,'%c')", i, 439 keyLayout[macVirtualKey]->qtKey[i], 440 keyLayout[macVirtualKey]->qtKey[i], 441 keyLayout[macVirtualKey]->qtKey[i]); 442 } 443#endif 444} 445 446QList<int> QCocoaKeyMapper::possibleKeys(const QKeyEvent *event) const 447{ 448 QList<int> ret; 449 const_cast<QCocoaKeyMapper *>(this)->updateKeyMap(event->nativeVirtualKey(), QChar(event->key())); 450 451 KeyboardLayoutItem *kbItem = keyLayout[event->nativeVirtualKey()]; 452 453 if (!kbItem) // Key is not in any keyboard layout (e.g. eisu-key on Japanese keyboard) 454 return ret; 455 456 int baseKey = kbItem->qtKey[0]; 457 Qt::KeyboardModifiers keyMods = event->modifiers(); 458 459 ret << int(baseKey + keyMods); // The base key is _always_ valid, of course 460 461 for (int i = 1; i < 8; ++i) { 462 Qt::KeyboardModifiers neededMods = ModsTbl[i]; 463 int key = kbItem->qtKey[i]; 464 if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) { 465 ret << int(key + (keyMods & ~neededMods)); 466 } 467 } 468 return ret; 469} 470 471QT_END_NAMESPACE 472