00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "CKeyMap.h"
00016 #include "KeyTypes.h"
00017 #include "CLog.h"
00018 #include <assert.h>
00019 #include <cctype>
00020 #include <cstdlib>
00021
00022 CKeyMap::CNameToKeyMap* CKeyMap::s_nameToKeyMap = NULL;
00023 CKeyMap::CNameToModifierMap* CKeyMap::s_nameToModifierMap = NULL;
00024 CKeyMap::CKeyToNameMap* CKeyMap::s_keyToNameMap = NULL;
00025 CKeyMap::CModifierToNameMap* CKeyMap::s_modifierToNameMap = NULL;
00026
00027 CKeyMap::CKeyMap() :
00028 m_numGroups(0),
00029 m_composeAcrossGroups(false)
00030 {
00031 m_modifierKeyItem.m_id = kKeyNone;
00032 m_modifierKeyItem.m_group = 0;
00033 m_modifierKeyItem.m_button = 0;
00034 m_modifierKeyItem.m_required = 0;
00035 m_modifierKeyItem.m_sensitive = 0;
00036 m_modifierKeyItem.m_generates = 0;
00037 m_modifierKeyItem.m_dead = false;
00038 m_modifierKeyItem.m_lock = false;
00039 m_modifierKeyItem.m_client = 0;
00040 }
00041
00042 CKeyMap::~CKeyMap()
00043 {
00044
00045 }
00046
00047 void
00048 CKeyMap::swap(CKeyMap& x)
00049 {
00050 m_keyIDMap.swap(x.m_keyIDMap);
00051 m_modifierKeys.swap(x.m_modifierKeys);
00052 m_halfDuplex.swap(x.m_halfDuplex);
00053 m_halfDuplexMods.swap(x.m_halfDuplexMods);
00054 SInt32 tmp1 = m_numGroups;
00055 m_numGroups = x.m_numGroups;
00056 x.m_numGroups = tmp1;
00057 bool tmp2 = m_composeAcrossGroups;
00058 m_composeAcrossGroups = x.m_composeAcrossGroups;
00059 x.m_composeAcrossGroups = tmp2;
00060 }
00061
00062 void
00063 CKeyMap::addKeyEntry(const KeyItem& item)
00064 {
00065
00066 if (item.m_id == kKeyNone) {
00067 return;
00068 }
00069
00070
00071 SInt32 numGroups = item.m_group + 1;
00072 if (getNumGroups() > numGroups) {
00073 numGroups = getNumGroups();
00074 }
00075 KeyGroupTable& groupTable = m_keyIDMap[item.m_id];
00076 if (groupTable.size() < static_cast<size_t>(numGroups)) {
00077 groupTable.resize(numGroups);
00078 }
00079
00080
00081 KeyItemList items;
00082 items.push_back(item);
00083
00084
00085 KeyItem& newItem = items.back();
00086 newItem.m_dead = isDeadKey(item.m_id);
00087
00088
00089 newItem.m_required &= newItem.m_sensitive;
00090
00091
00092 KeyEntryList& entries = groupTable[item.m_group];
00093 for (size_t i = 0, n = entries.size(); i < n; ++i) {
00094 if (entries[i].size() == 1 && newItem == entries[i][0]) {
00095 return;
00096 }
00097 }
00098
00099
00100 entries.push_back(items);
00101 LOG((CLOG_DEBUG1 "add key: %04x %d %03x %04x (%04x %04x %04x)%s", newItem.m_id, newItem.m_group, newItem.m_button, newItem.m_client, newItem.m_required, newItem.m_sensitive, newItem.m_generates, newItem.m_dead ? " dead" : ""));
00102 }
00103
00104 void
00105 CKeyMap::addKeyAliasEntry(KeyID targetID, SInt32 group,
00106 KeyModifierMask targetRequired,
00107 KeyModifierMask targetSensitive,
00108 KeyID sourceID,
00109 KeyModifierMask sourceRequired,
00110 KeyModifierMask sourceSensitive)
00111 {
00112
00113 if (findCompatibleKey(targetID, group, targetRequired,
00114 targetSensitive) != NULL) {
00115 return;
00116 }
00117
00118
00119 for (SInt32 gd = 0, n = getNumGroups(); gd < n; ++gd) {
00120 SInt32 eg = getEffectiveGroup(group, gd);
00121 const KeyItemList* sourceEntry =
00122 findCompatibleKey(sourceID, eg,
00123 sourceRequired, sourceSensitive);
00124 if (sourceEntry != NULL && sourceEntry->size() == 1) {
00125 CKeyMap::KeyItem targetItem = sourceEntry->back();
00126 targetItem.m_id = targetID;
00127 targetItem.m_group = eg;
00128 addKeyEntry(targetItem);
00129 break;
00130 }
00131 }
00132 }
00133
00134 bool
00135 CKeyMap::addKeyCombinationEntry(KeyID id, SInt32 group,
00136 const KeyID* keys, UInt32 numKeys)
00137 {
00138
00139 if (id == kKeyNone) {
00140 return false;
00141 }
00142
00143 SInt32 numGroups = group + 1;
00144 if (getNumGroups() > numGroups) {
00145 numGroups = getNumGroups();
00146 }
00147 KeyGroupTable& groupTable = m_keyIDMap[id];
00148 if (groupTable.size() < static_cast<size_t>(numGroups)) {
00149 groupTable.resize(numGroups);
00150 }
00151 if (!groupTable[group].empty()) {
00152
00153 return false;
00154 }
00155
00156
00157 KeyItemList items;
00158 for (UInt32 i = 0; i < numKeys; ++i) {
00159 KeyIDMap::const_iterator gtIndex = m_keyIDMap.find(keys[i]);
00160 if (gtIndex == m_keyIDMap.end()) {
00161 return false;
00162 }
00163 const KeyGroupTable& groupTable = gtIndex->second;
00164
00165
00166
00167 SInt32 n = 1;
00168 if (m_composeAcrossGroups) {
00169 n = (SInt32)groupTable.size();
00170 }
00171
00172 bool found = false;
00173 for (SInt32 gd = 0; gd < n && !found; ++gd) {
00174 SInt32 eg = (group + gd) % getNumGroups();
00175 const KeyEntryList& entries = groupTable[eg];
00176 for (size_t j = 0; j < entries.size(); ++j) {
00177 if (entries[j].size() == 1) {
00178 found = true;
00179 items.push_back(entries[j][0]);
00180 break;
00181 }
00182 }
00183 }
00184 if (!found) {
00185
00186 return false;
00187 }
00188 }
00189
00190
00191 groupTable[group].push_back(items);
00192 return true;
00193 }
00194
00195 void
00196 CKeyMap::allowGroupSwitchDuringCompose()
00197 {
00198 m_composeAcrossGroups = true;
00199 }
00200
00201 void
00202 CKeyMap::addHalfDuplexButton(KeyButton button)
00203 {
00204 m_halfDuplex.insert(button);
00205 }
00206
00207 void
00208 CKeyMap::clearHalfDuplexModifiers()
00209 {
00210 m_halfDuplexMods.clear();
00211 }
00212
00213 void
00214 CKeyMap::addHalfDuplexModifier(KeyID key)
00215 {
00216 m_halfDuplexMods.insert(key);
00217 }
00218
00219 void
00220 CKeyMap::finish()
00221 {
00222 m_numGroups = findNumGroups();
00223
00224
00225 for (KeyIDMap::iterator i = m_keyIDMap.begin();
00226 i != m_keyIDMap.end(); ++i) {
00227 i->second.resize(m_numGroups);
00228 }
00229
00230
00231 setModifierKeys();
00232 }
00233
00234 void
00235 CKeyMap::foreachKey(ForeachKeyCallback cb, void* userData)
00236 {
00237 for (KeyIDMap::iterator i = m_keyIDMap.begin();
00238 i != m_keyIDMap.end(); ++i) {
00239 KeyGroupTable& groupTable = i->second;
00240 for (size_t group = 0; group < groupTable.size(); ++group) {
00241 KeyEntryList& entryList = groupTable[group];
00242 for (size_t j = 0; j < entryList.size(); ++j) {
00243 KeyItemList& itemList = entryList[j];
00244 for (size_t k = 0; k < itemList.size(); ++k) {
00245 (*cb)(i->first, static_cast<SInt32>(group),
00246 itemList[k], userData);
00247 }
00248 }
00249 }
00250 }
00251 }
00252
00253 const CKeyMap::KeyItem*
00254 CKeyMap::mapKey(Keystrokes& keys, KeyID id, SInt32 group,
00255 ModifierToKeys& activeModifiers,
00256 KeyModifierMask& currentState,
00257 KeyModifierMask desiredMask,
00258 bool isAutoRepeat) const
00259 {
00260 LOG((CLOG_DEBUG1 "mapKey %04x (%d) with mask %04x, start state: %04x", id, id, desiredMask, currentState));
00261
00262
00263 if (id == kKeyNextGroup) {
00264 keys.push_back(Keystroke(1, false, false));
00265 return NULL;
00266 }
00267 else if (id == kKeyPrevGroup) {
00268 keys.push_back(Keystroke(-1, false, false));
00269 return NULL;
00270 }
00271
00272 const KeyItem* item;
00273 switch (id) {
00274 case kKeyShift_L:
00275 case kKeyShift_R:
00276 case kKeyControl_L:
00277 case kKeyControl_R:
00278 case kKeyAlt_L:
00279 case kKeyAlt_R:
00280 case kKeyMeta_L:
00281 case kKeyMeta_R:
00282 case kKeySuper_L:
00283 case kKeySuper_R:
00284 case kKeyAltGr:
00285 case kKeyCapsLock:
00286 case kKeyNumLock:
00287 case kKeyScrollLock:
00288 item = mapModifierKey(keys, id, group, activeModifiers,
00289 currentState, desiredMask, isAutoRepeat);
00290 break;
00291
00292 case kKeySetModifiers:
00293 if (!keysForModifierState(0, group, activeModifiers, currentState,
00294 desiredMask, desiredMask, 0, keys)) {
00295 LOG((CLOG_DEBUG1 "unable to set modifiers %04x", desiredMask));
00296 return NULL;
00297 }
00298 return &m_modifierKeyItem;
00299
00300 case kKeyClearModifiers:
00301 if (!keysForModifierState(0, group, activeModifiers, currentState,
00302 currentState & ~desiredMask,
00303 desiredMask, 0, keys)) {
00304 LOG((CLOG_DEBUG1 "unable to clear modifiers %04x", desiredMask));
00305 return NULL;
00306 }
00307 return &m_modifierKeyItem;
00308
00309 default:
00310 if (isCommand(desiredMask)) {
00311 item = mapCommandKey(keys, id, group, activeModifiers,
00312 currentState, desiredMask, isAutoRepeat);
00313 }
00314 else {
00315 item = mapCharacterKey(keys, id, group, activeModifiers,
00316 currentState, desiredMask, isAutoRepeat);
00317 }
00318 break;
00319 }
00320
00321 if (item != NULL) {
00322 LOG((CLOG_DEBUG1 "mapped to %03x, new state %04x", item->m_button, currentState));
00323 }
00324 return item;
00325 }
00326
00327 SInt32
00328 CKeyMap::getNumGroups() const
00329 {
00330 return m_numGroups;
00331 }
00332
00333 SInt32
00334 CKeyMap::getEffectiveGroup(SInt32 group, SInt32 offset) const
00335 {
00336 return (group + offset + getNumGroups()) % getNumGroups();
00337 }
00338
00339 const CKeyMap::KeyItemList*
00340 CKeyMap::findCompatibleKey(KeyID id, SInt32 group,
00341 KeyModifierMask required, KeyModifierMask sensitive) const
00342 {
00343 assert(group >= 0 && group < getNumGroups());
00344
00345 KeyIDMap::const_iterator i = m_keyIDMap.find(id);
00346 if (i == m_keyIDMap.end()) {
00347 return NULL;
00348 }
00349
00350 const KeyEntryList& entries = i->second[group];
00351 for (size_t j = 0; j < entries.size(); ++j) {
00352 if ((entries[j].back().m_sensitive & sensitive) == 0 ||
00353 (entries[j].back().m_required & sensitive) ==
00354 (required & sensitive)) {
00355 return &entries[j];
00356 }
00357 }
00358
00359 return NULL;
00360 }
00361
00362 bool
00363 CKeyMap::isHalfDuplex(KeyID key, KeyButton button) const
00364 {
00365 return (m_halfDuplex.count(button) + m_halfDuplexMods.count(key) > 0);
00366 }
00367
00368 bool
00369 CKeyMap::isCommand(KeyModifierMask mask) const
00370 {
00371 return ((mask & getCommandModifiers()) != 0);
00372 }
00373
00374 KeyModifierMask
00375 CKeyMap::getCommandModifiers() const
00376 {
00377
00378
00379
00380 return KeyModifierControl |
00381 KeyModifierAlt |
00382 KeyModifierMeta |
00383 KeyModifierSuper;
00384 }
00385
00386 void
00387 CKeyMap::collectButtons(const ModifierToKeys& mods, ButtonToKeyMap& keys)
00388 {
00389 keys.clear();
00390 for (ModifierToKeys::const_iterator i = mods.begin();
00391 i != mods.end(); ++i) {
00392 keys.insert(std::make_pair(i->second.m_button, &i->second));
00393 }
00394 }
00395
00396 void
00397 CKeyMap::initModifierKey(KeyItem& item)
00398 {
00399 item.m_generates = 0;
00400 item.m_lock = false;
00401 switch (item.m_id) {
00402 case kKeyShift_L:
00403 case kKeyShift_R:
00404 item.m_generates = KeyModifierShift;
00405 break;
00406
00407 case kKeyControl_L:
00408 case kKeyControl_R:
00409 item.m_generates = KeyModifierControl;
00410 break;
00411
00412 case kKeyAlt_L:
00413 case kKeyAlt_R:
00414 item.m_generates = KeyModifierAlt;
00415 break;
00416
00417 case kKeyMeta_L:
00418 case kKeyMeta_R:
00419 item.m_generates = KeyModifierMeta;
00420 break;
00421
00422 case kKeySuper_L:
00423 case kKeySuper_R:
00424 item.m_generates = KeyModifierSuper;
00425 break;
00426
00427 case kKeyAltGr:
00428 item.m_generates = KeyModifierAltGr;
00429 break;
00430
00431 case kKeyCapsLock:
00432 item.m_generates = KeyModifierCapsLock;
00433 item.m_lock = true;
00434 break;
00435
00436 case kKeyNumLock:
00437 item.m_generates = KeyModifierNumLock;
00438 item.m_lock = true;
00439 break;
00440
00441 case kKeyScrollLock:
00442 item.m_generates = KeyModifierScrollLock;
00443 item.m_lock = true;
00444 break;
00445
00446 default:
00447
00448 break;
00449 }
00450 }
00451
00452 SInt32
00453 CKeyMap::findNumGroups() const
00454 {
00455 size_t max = 0;
00456 for (KeyIDMap::const_iterator i = m_keyIDMap.begin();
00457 i != m_keyIDMap.end(); ++i) {
00458 if (i->second.size() > max) {
00459 max = i->second.size();
00460 }
00461 }
00462 return static_cast<SInt32>(max);
00463 }
00464
00465 void
00466 CKeyMap::setModifierKeys()
00467 {
00468 m_modifierKeys.clear();
00469 m_modifierKeys.resize(kKeyModifierNumBits * getNumGroups());
00470 for (KeyIDMap::const_iterator i = m_keyIDMap.begin();
00471 i != m_keyIDMap.end(); ++i) {
00472 const KeyGroupTable& groupTable = i->second;
00473 for (size_t g = 0; g < groupTable.size(); ++g) {
00474 const KeyEntryList& entries = groupTable[g];
00475 for (size_t j = 0; j < entries.size(); ++j) {
00476
00477 if (entries[j].size() != 1) {
00478 continue;
00479 }
00480
00481
00482 const KeyItem& item = entries[j].back();
00483 if (item.m_generates == 0) {
00484 continue;
00485 }
00486
00487
00488 for (SInt32 b = 0; b < kKeyModifierNumBits; ++b) {
00489
00490 if (((1u << b) & item.m_generates) != 0) {
00491 SInt32 mIndex = g * kKeyModifierNumBits + b;
00492 m_modifierKeys[mIndex].push_back(&item);
00493 }
00494 }
00495 }
00496 }
00497 }
00498 }
00499
00500 const CKeyMap::KeyItem*
00501 CKeyMap::mapCommandKey(Keystrokes& keys, KeyID id, SInt32 group,
00502 ModifierToKeys& activeModifiers,
00503 KeyModifierMask& currentState,
00504 KeyModifierMask desiredMask,
00505 bool isAutoRepeat) const
00506 {
00507 static const KeyModifierMask s_overrideModifiers = 0xffffu;
00508
00509
00510 KeyIDMap::const_iterator i = m_keyIDMap.find(id);
00511 if (i == m_keyIDMap.end()) {
00512
00513 LOG((CLOG_DEBUG1 "key %04x is not on keyboard", id));
00514 return NULL;
00515 }
00516 const KeyGroupTable& keyGroupTable = i->second;
00517
00518
00519 const KeyItem* keyItem = NULL;
00520 SInt32 numGroups = getNumGroups();
00521 for (SInt32 groupOffset = 0; groupOffset < numGroups; ++groupOffset) {
00522 SInt32 effectiveGroup = getEffectiveGroup(group, groupOffset);
00523 const KeyEntryList& entryList = keyGroupTable[effectiveGroup];
00524 for (size_t i = 0; i < entryList.size(); ++i) {
00525 if (entryList[i].size() != 1) {
00526
00527 continue;
00528 }
00529
00530
00531
00532
00533
00534 const KeyItem& item = entryList[i].back();
00535 if ((item.m_required & KeyModifierShift & desiredMask) ==
00536 (item.m_sensitive & KeyModifierShift & desiredMask)) {
00537 LOG((CLOG_DEBUG1 "found key in group %d", effectiveGroup));
00538 keyItem = &item;
00539 break;
00540 }
00541 }
00542 if (keyItem != NULL) {
00543 break;
00544 }
00545 }
00546 if (keyItem == NULL) {
00547
00548 LOG((CLOG_DEBUG1 "no mapping for key %04x", id));
00549 return NULL;
00550 }
00551
00552
00553 ModifierToKeys newModifiers = activeModifiers;
00554 KeyModifierMask newState = currentState;
00555 SInt32 newGroup = group;
00556
00557
00558 desiredMask = (desiredMask & ~KeyModifierCapsLock) |
00559 (currentState & KeyModifierCapsLock);
00560
00561
00562 if (!keysForKeyItem(*keyItem, newGroup, newModifiers,
00563 newState, desiredMask,
00564 s_overrideModifiers, isAutoRepeat, keys)) {
00565 LOG((CLOG_DEBUG1 "can't map key"));
00566 keys.clear();
00567 return NULL;
00568 }
00569
00570
00571 if (!keysToRestoreModifiers(*keyItem, group, newModifiers, newState,
00572 activeModifiers, keys)) {
00573 LOG((CLOG_DEBUG1 "failed to restore modifiers"));
00574 keys.clear();
00575 return NULL;
00576 }
00577
00578
00579 if (newGroup != group) {
00580 keys.push_back(Keystroke(group, true, true));
00581 }
00582
00583
00584 activeModifiers = newModifiers;
00585 currentState = newState;
00586
00587 return keyItem;
00588 }
00589
00590 const CKeyMap::KeyItem*
00591 CKeyMap::mapCharacterKey(Keystrokes& keys, KeyID id, SInt32 group,
00592 ModifierToKeys& activeModifiers,
00593 KeyModifierMask& currentState,
00594 KeyModifierMask desiredMask,
00595 bool isAutoRepeat) const
00596 {
00597
00598 KeyIDMap::const_iterator i = m_keyIDMap.find(id);
00599 if (i == m_keyIDMap.end()) {
00600
00601 LOG((CLOG_DEBUG1 "key %04x is not on keyboard", id));
00602 return NULL;
00603 }
00604 const KeyGroupTable& keyGroupTable = i->second;
00605
00606
00607 SInt32 keyIndex = -1;
00608 SInt32 numGroups = getNumGroups();
00609 SInt32 groupOffset;
00610 LOG((CLOG_DEBUG1 "find best: %04x %04x", currentState, desiredMask));
00611 for (groupOffset = 0; groupOffset < numGroups; ++groupOffset) {
00612 SInt32 effectiveGroup = getEffectiveGroup(group, groupOffset);
00613 keyIndex = findBestKey(keyGroupTable[effectiveGroup],
00614 currentState, desiredMask);
00615 if (keyIndex != -1) {
00616 LOG((CLOG_DEBUG1 "found key in group %d", effectiveGroup));
00617 break;
00618 }
00619 }
00620 if (keyIndex == -1) {
00621
00622 LOG((CLOG_DEBUG1 "no mapping for key %04x", id));
00623 return NULL;
00624 }
00625
00626
00627 SInt32 effectiveGroup = getEffectiveGroup(group, groupOffset);
00628 const KeyItemList& itemList = keyGroupTable[effectiveGroup][keyIndex];
00629 if (itemList.empty()) {
00630 return NULL;
00631 }
00632 const KeyItem& keyItem = itemList.back();
00633
00634
00635 ModifierToKeys newModifiers = activeModifiers;
00636 KeyModifierMask newState = currentState;
00637 SInt32 newGroup = group;
00638
00639
00640 for (size_t j = 0; j < itemList.size(); ++j) {
00641 if (!keysForKeyItem(itemList[j], newGroup, newModifiers,
00642 newState, desiredMask,
00643 0, isAutoRepeat, keys)) {
00644 LOG((CLOG_DEBUG1 "can't map key"));
00645 keys.clear();
00646 return NULL;
00647 }
00648 }
00649
00650
00651 if (!keysToRestoreModifiers(keyItem, group, newModifiers, newState,
00652 activeModifiers, keys)) {
00653 LOG((CLOG_DEBUG1 "failed to restore modifiers"));
00654 keys.clear();
00655 return NULL;
00656 }
00657
00658
00659 if (newGroup != group) {
00660 keys.push_back(Keystroke(group, true, true));
00661 }
00662
00663
00664 activeModifiers = newModifiers;
00665 currentState = newState;
00666
00667 return &keyItem;
00668 }
00669
00670 const CKeyMap::KeyItem*
00671 CKeyMap::mapModifierKey(Keystrokes& keys, KeyID id, SInt32 group,
00672 ModifierToKeys& activeModifiers,
00673 KeyModifierMask& currentState,
00674 KeyModifierMask desiredMask,
00675 bool isAutoRepeat) const
00676 {
00677 return mapCharacterKey(keys, id, group, activeModifiers,
00678 currentState, desiredMask, isAutoRepeat);
00679 }
00680
00681 SInt32
00682 CKeyMap::findBestKey(const KeyEntryList& entryList,
00683 KeyModifierMask ,
00684 KeyModifierMask desiredState) const
00685 {
00686
00687 for (size_t i = 0; i < entryList.size(); ++i) {
00688 const KeyItem& item = entryList[i].back();
00689 if ((item.m_required & desiredState) ==
00690 (item.m_sensitive & desiredState)) {
00691 LOG((CLOG_DEBUG1 "best key index %d of %d (exact)", i, entryList.size()));
00692 return i;
00693 }
00694 }
00695
00696
00697 SInt32 bestCount = 32;
00698 SInt32 bestIndex = -1;
00699 for (size_t i = 0; i < entryList.size(); ++i) {
00700 const KeyItem& item = entryList[i].back();
00701 KeyModifierMask change =
00702 ((item.m_required ^ desiredState) & item.m_sensitive);
00703 SInt32 n = getNumModifiers(change);
00704 if (n < bestCount) {
00705 bestCount = n;
00706 bestIndex = i;
00707 }
00708 }
00709 if (bestIndex != -1) {
00710 LOG((CLOG_DEBUG1 "best key index %d of %d (%d modifiers)", bestIndex, entryList.size(), bestCount));
00711 }
00712
00713 return bestIndex;
00714 }
00715
00716
00717 const CKeyMap::KeyItem*
00718 CKeyMap::keyForModifier(KeyButton button, SInt32 group,
00719 SInt32 modifierBit) const
00720 {
00721 assert(modifierBit >= 0 && modifierBit < kKeyModifierNumBits);
00722 assert(group >= 0 && group < getNumGroups());
00723
00724
00725
00726
00727
00728
00729 const ModifierKeyItemList& items =
00730 m_modifierKeys[group * kKeyModifierNumBits + modifierBit];
00731 for (ModifierKeyItemList::const_iterator i = items.begin();
00732 i != items.end(); ++i) {
00733 if ((*i)->m_button != button) {
00734 return (*i);
00735 }
00736 }
00737 return NULL;
00738 }
00739
00740 bool
00741 CKeyMap::keysForKeyItem(const KeyItem& keyItem, SInt32& group,
00742 ModifierToKeys& activeModifiers,
00743 KeyModifierMask& currentState, KeyModifierMask desiredState,
00744 KeyModifierMask overrideModifiers,
00745 bool isAutoRepeat,
00746 Keystrokes& keystrokes) const
00747 {
00748 static const KeyModifierMask s_notRequiredMask =
00749 KeyModifierAltGr | KeyModifierNumLock | KeyModifierScrollLock;
00750
00751
00752 if (group != keyItem.m_group) {
00753 group = keyItem.m_group;
00754 keystrokes.push_back(Keystroke(group, true, false));
00755 }
00756
00757 EKeystroke type;
00758 if (keyItem.m_dead) {
00759
00760 if (!keysForModifierState(keyItem.m_button, group,
00761 activeModifiers, currentState,
00762 keyItem.m_required, keyItem.m_sensitive,
00763 0, keystrokes)) {
00764 LOG((CLOG_DEBUG1 "unable to match modifier state for dead key %d", keyItem.m_button));
00765 return false;
00766 }
00767
00768
00769 type = kKeystrokeClick;
00770 }
00771 else {
00772
00773
00774 KeyModifierMask sensitive = keyItem.m_sensitive & ~overrideModifiers;
00775
00776
00777
00778
00779
00780
00781
00782
00783 LOG((CLOG_DEBUG1 "state: %04x,%04x,%04x", currentState, keyItem.m_required, sensitive));
00784 if (!keysForModifierState(keyItem.m_button, group,
00785 activeModifiers, currentState,
00786 keyItem.m_required, sensitive,
00787 0, keystrokes)) {
00788 LOG((CLOG_DEBUG1 "unable to match modifier state (%04x,%04x) for key %d", keyItem.m_required, keyItem.m_sensitive, keyItem.m_button));
00789 return false;
00790 }
00791
00792
00793
00794
00795 LOG((CLOG_DEBUG1 "desired state: %04x %04x,%04x,%04x", desiredState, currentState, keyItem.m_required, keyItem.m_sensitive));
00796 if (!keysForModifierState(keyItem.m_button, group,
00797 activeModifiers, currentState,
00798 desiredState,
00799 ~(sensitive | keyItem.m_generates),
00800 s_notRequiredMask, keystrokes)) {
00801 LOG((CLOG_DEBUG1 "unable to match desired modifier state (%04x,%04x) for key %d", desiredState, ~keyItem.m_sensitive & 0xffffu, keyItem.m_button));
00802 return false;
00803 }
00804
00805
00806 type = isAutoRepeat ? kKeystrokeRepeat : kKeystrokePress;
00807 }
00808 addKeystrokes(type, keyItem, activeModifiers, currentState, keystrokes);
00809
00810 return true;
00811 }
00812
00813 bool
00814 CKeyMap::keysToRestoreModifiers(const KeyItem& keyItem, SInt32,
00815 ModifierToKeys& activeModifiers,
00816 KeyModifierMask& currentState,
00817 const ModifierToKeys& desiredModifiers,
00818 Keystrokes& keystrokes) const
00819 {
00820
00821
00822 ModifierToKeys oldModifiers = activeModifiers;
00823
00824
00825 ButtonToKeyMap oldKeys, newKeys;
00826 collectButtons(oldModifiers, oldKeys);
00827 collectButtons(desiredModifiers, newKeys);
00828
00829
00830 for (ModifierToKeys::const_iterator i = oldModifiers.begin();
00831 i != oldModifiers.end(); ++i) {
00832 KeyButton button = i->second.m_button;
00833 if (button != keyItem.m_button && newKeys.count(button) == 0) {
00834 EKeystroke type = kKeystrokeRelease;
00835 if (i->second.m_lock) {
00836 type = kKeystrokeUnmodify;
00837 }
00838 addKeystrokes(type, i->second,
00839 activeModifiers, currentState, keystrokes);
00840 }
00841 }
00842
00843
00844 for (ModifierToKeys::const_iterator i = desiredModifiers.begin();
00845 i != desiredModifiers.end(); ++i) {
00846 KeyButton button = i->second.m_button;
00847 if (button != keyItem.m_button && oldKeys.count(button) == 0) {
00848 EKeystroke type = kKeystrokePress;
00849 if (i->second.m_lock) {
00850 type = kKeystrokeModify;
00851 }
00852 addKeystrokes(type, i->second,
00853 activeModifiers, currentState, keystrokes);
00854 }
00855 }
00856
00857 return true;
00858 }
00859
00860 bool
00861 CKeyMap::keysForModifierState(KeyButton button, SInt32 group,
00862 ModifierToKeys& activeModifiers,
00863 KeyModifierMask& currentState,
00864 KeyModifierMask requiredState, KeyModifierMask sensitiveMask,
00865 KeyModifierMask notRequiredMask,
00866 Keystrokes& keystrokes) const
00867 {
00868
00869 KeyModifierMask flipMask = ((currentState ^ requiredState) & sensitiveMask);
00870
00871
00872
00873
00874
00875 flipMask &= ~notRequiredMask;
00876 LOG((CLOG_DEBUG1 "flip: %04x (%04x vs %04x in %04x - %04x)", flipMask, currentState, requiredState, sensitiveMask & 0xffffu, notRequiredMask & 0xffffu));
00877 if (flipMask == 0) {
00878 return true;
00879 }
00880
00881
00882
00883
00884
00885
00886
00887 for (SInt32 bit = kKeyModifierNumBits; bit-- > 0; ) {
00888 KeyModifierMask mask = (1u << bit);
00889 if ((flipMask & mask) == 0) {
00890
00891 continue;
00892 }
00893
00894
00895 bool active = ((requiredState & mask) != 0);
00896
00897
00898 const KeyItem* keyItem = keyForModifier(button, group, bit);
00899 if (keyItem == NULL) {
00900 if ((mask & notRequiredMask) == 0) {
00901 LOG((CLOG_DEBUG1 "no key for modifier %04x", mask));
00902 return false;
00903 }
00904 else {
00905 continue;
00906 }
00907 }
00908
00909
00910
00911
00912 KeyModifierMask sensitive = keyItem->m_sensitive;
00913 if ((sensitive & mask) != 0) {
00914
00915
00916 LOG((CLOG_DEBUG1 "modifier %04x modified by itself", mask));
00917 sensitive &= ~mask;
00918 }
00919 if (sensitive != 0) {
00920 if (sensitive > mask) {
00921
00922 LOG((CLOG_DEBUG1 "modifier %04x modified by %04x", mask, sensitive));
00923 return false;
00924 }
00925 if (active && !keysForModifierState(button, group,
00926 activeModifiers, currentState,
00927 keyItem->m_required, sensitive,
00928 notRequiredMask, keystrokes)) {
00929 return false;
00930 }
00931 else if (!active) {
00932
00933
00934
00935
00936
00937 }
00938 }
00939
00940
00941 if ((currentState & sensitive) != (keyItem->m_required & sensitive)) {
00942 LOG((CLOG_DEBUG1 "unable to match modifier state for modifier %04x (%04x vs %04x in %04x)", mask, currentState, keyItem->m_required, sensitive));
00943 return false;
00944 }
00945
00946
00947 EKeystroke type = active ? kKeystrokeModify : kKeystrokeUnmodify;
00948 addKeystrokes(type, *keyItem, activeModifiers, currentState,
00949 keystrokes);
00950 }
00951
00952 return true;
00953 }
00954
00955 void
00956 CKeyMap::addKeystrokes(EKeystroke type, const KeyItem& keyItem,
00957 ModifierToKeys& activeModifiers,
00958 KeyModifierMask& currentState,
00959 Keystrokes& keystrokes) const
00960 {
00961 KeyButton button = keyItem.m_button;
00962 UInt32 data = keyItem.m_client;
00963 switch (type) {
00964 case kKeystrokePress:
00965 keystrokes.push_back(Keystroke(button, true, false, data));
00966 if (keyItem.m_generates != 0) {
00967 if (!keyItem.m_lock || (currentState & keyItem.m_generates) == 0) {
00968
00969 activeModifiers.insert(std::make_pair(
00970 keyItem.m_generates, keyItem));
00971 currentState |= keyItem.m_generates;
00972 }
00973 else {
00974
00975 activeModifiers.erase(keyItem.m_generates);
00976 currentState &= ~keyItem.m_generates;
00977 }
00978 }
00979 break;
00980
00981 case kKeystrokeRelease:
00982 keystrokes.push_back(Keystroke(button, false, false, data));
00983 if (keyItem.m_generates != 0 && !keyItem.m_lock) {
00984
00985 std::pair<ModifierToKeys::iterator,
00986 ModifierToKeys::iterator> range =
00987 activeModifiers.equal_range(keyItem.m_generates);
00988 for (ModifierToKeys::iterator i = range.first;
00989 i != range.second; ++i) {
00990 if (i->second.m_button == button) {
00991 activeModifiers.erase(i);
00992 break;
00993 }
00994 }
00995
00996
00997 if (activeModifiers.count(keyItem.m_generates) == 0) {
00998 currentState &= ~keyItem.m_generates;
00999 }
01000 }
01001 break;
01002
01003 case kKeystrokeRepeat:
01004 keystrokes.push_back(Keystroke(button, false, true, data));
01005 keystrokes.push_back(Keystroke(button, true, true, data));
01006
01007 break;
01008
01009 case kKeystrokeClick:
01010 keystrokes.push_back(Keystroke(button, true, false, data));
01011 keystrokes.push_back(Keystroke(button, false, false, data));
01012
01013 break;
01014
01015 case kKeystrokeModify:
01016 case kKeystrokeUnmodify:
01017 if (keyItem.m_lock) {
01018
01019 if (m_halfDuplex.count(button) > 0) {
01020 if (type == kKeystrokeModify) {
01021
01022 keystrokes.push_back(Keystroke(button, true, false, data));
01023 }
01024 else {
01025
01026 keystrokes.push_back(Keystroke(button, false, false, data));
01027 }
01028 }
01029 else {
01030
01031 keystrokes.push_back(Keystroke(button, true, false, data));
01032 keystrokes.push_back(Keystroke(button, false, false, data));
01033 }
01034 }
01035 else if (type == kKeystrokeModify) {
01036
01037 keystrokes.push_back(Keystroke(button, true, false, data));
01038 }
01039 else {
01040
01041
01042 std::pair<ModifierToKeys::const_iterator,
01043 ModifierToKeys::const_iterator> range =
01044 activeModifiers.equal_range(keyItem.m_generates);
01045 for (ModifierToKeys::const_iterator i = range.first;
01046 i != range.second; ++i) {
01047 keystrokes.push_back(Keystroke(i->second.m_button,
01048 false, false, i->second.m_client));
01049 }
01050 }
01051
01052 if (type == kKeystrokeModify) {
01053 activeModifiers.insert(std::make_pair(
01054 keyItem.m_generates, keyItem));
01055 currentState |= keyItem.m_generates;
01056 }
01057 else {
01058 activeModifiers.erase(keyItem.m_generates);
01059 currentState &= ~keyItem.m_generates;
01060 }
01061 break;
01062 }
01063 }
01064
01065 SInt32
01066 CKeyMap::getNumModifiers(KeyModifierMask state)
01067 {
01068 SInt32 n = 0;
01069 for (; state != 0; state >>= 1) {
01070 if ((state & 1) != 0) {
01071 ++n;
01072 }
01073 }
01074 return n;
01075 }
01076
01077 bool
01078 CKeyMap::isDeadKey(KeyID key)
01079 {
01080 return (key == kKeyCompose || (key >= 0x0300 && key <= 0x036f));
01081 }
01082
01083 KeyID
01084 CKeyMap::getDeadKey(KeyID key)
01085 {
01086 if (isDeadKey(key)) {
01087
01088 return key;
01089 }
01090
01091 switch (key) {
01092 case '`':
01093 return kKeyDeadGrave;
01094
01095 case 0xb4u:
01096 return kKeyDeadAcute;
01097
01098 case '^':
01099 case 0x2c6:
01100 return kKeyDeadCircumflex;
01101
01102 case '~':
01103 case 0x2dcu:
01104 return kKeyDeadTilde;
01105
01106 case 0xafu:
01107 return kKeyDeadMacron;
01108
01109 case 0x2d8u:
01110 return kKeyDeadBreve;
01111
01112 case 0x2d9u:
01113 return kKeyDeadAbovedot;
01114
01115 case 0xa8u:
01116 return kKeyDeadDiaeresis;
01117
01118 case 0xb0u:
01119 case 0x2dau:
01120 return kKeyDeadAbovering;
01121
01122 case '\"':
01123 case 0x2ddu:
01124 return kKeyDeadDoubleacute;
01125
01126 case 0x2c7u:
01127 return kKeyDeadCaron;
01128
01129 case 0xb8u:
01130 return kKeyDeadCedilla;
01131
01132 case 0x2dbu:
01133 return kKeyDeadOgonek;
01134
01135 default:
01136
01137 return kKeyNone;
01138 }
01139 }
01140
01141 CString
01142 CKeyMap::formatKey(KeyID key, KeyModifierMask mask)
01143 {
01144
01145 initKeyNameMaps();
01146
01147 CString x;
01148 for (SInt32 i = 0; i < kKeyModifierNumBits; ++i) {
01149 KeyModifierMask mod = (1u << i);
01150 if ((mask & mod) != 0 && s_modifierToNameMap->count(mod) > 0) {
01151 x += s_modifierToNameMap->find(mod)->second;
01152 x += "+";
01153 }
01154 }
01155 if (key != kKeyNone) {
01156 if (s_keyToNameMap->count(key) > 0) {
01157 x += s_keyToNameMap->find(key)->second;
01158 }
01159
01160 else if (key >= 33 && key < 127) {
01161 x += (char)key;
01162 }
01163 else {
01164 x += CStringUtil::print("\\u%04x", key);
01165 }
01166 }
01167 else if (!x.empty()) {
01168
01169 x.erase(x.size() - 1);
01170 }
01171 return x;
01172 }
01173
01174 bool
01175 CKeyMap::parseKey(const CString& x, KeyID& key)
01176 {
01177
01178 initKeyNameMaps();
01179
01180
01181 key = kKeyNone;
01182 if (s_nameToKeyMap->count(x) > 0) {
01183 key = s_nameToKeyMap->find(x)->second;
01184 }
01185
01186 else if (x.size() == 1) {
01187 if (!isgraph(x[0])) {
01188
01189 return false;
01190 }
01191 key = (KeyID)x[0];
01192 }
01193 else if (x.size() == 6 && x[0] == '\\' && x[1] == 'u') {
01194
01195 char* end;
01196 key = (KeyID)strtol(x.c_str() + 2, &end, 16);
01197 if (*end != '\0') {
01198 return false;
01199 }
01200 }
01201 else if (!x.empty()) {
01202
01203 return false;
01204 }
01205
01206 return true;
01207 }
01208
01209 bool
01210 CKeyMap::parseModifiers(CString& x, KeyModifierMask& mask)
01211 {
01212
01213 initKeyNameMaps();
01214
01215 mask = 0;
01216 CString::size_type tb = x.find_first_not_of(" \t", 0);
01217 while (tb != CString::npos) {
01218
01219 CString::size_type te = x.find_first_of(" \t+)", tb);
01220 if (te == CString::npos) {
01221 te = x.size();
01222 }
01223 CString c = x.substr(tb, te - tb);
01224 if (c.empty()) {
01225
01226 return false;
01227 }
01228
01229 if (s_nameToModifierMap->count(c) > 0) {
01230 KeyModifierMask mod = s_nameToModifierMap->find(c)->second;
01231 if ((mask & mod) != 0) {
01232
01233 return false;
01234 }
01235 mask |= mod;
01236 }
01237 else {
01238
01239 x.erase(0, tb);
01240 CString::size_type tb = x.find_first_not_of(" \t");
01241 CString::size_type te = x.find_last_not_of(" \t");
01242 if (tb == CString::npos) {
01243 x = "";
01244 }
01245 else {
01246 x = x.substr(tb, te - tb + 1);
01247 }
01248 return true;
01249 }
01250
01251
01252 tb = x.find_first_not_of(" \t", te);
01253 if (tb != CString::npos) {
01254 if (x[tb] != '+') {
01255
01256 return false;
01257 }
01258 tb = x.find_first_not_of(" \t", tb + 1);
01259 }
01260 }
01261
01262
01263 x = "";
01264 return true;
01265 }
01266
01267 void
01268 CKeyMap::initKeyNameMaps()
01269 {
01270
01271 if (s_nameToKeyMap == NULL) {
01272 s_nameToKeyMap = new CNameToKeyMap;
01273 s_keyToNameMap = new CKeyToNameMap;
01274 for (const KeyNameMapEntry* i = kKeyNameMap; i->m_name != NULL; ++i) {
01275 (*s_nameToKeyMap)[i->m_name] = i->m_id;
01276 (*s_keyToNameMap)[i->m_id] = i->m_name;
01277 }
01278 }
01279 if (s_nameToModifierMap == NULL) {
01280 s_nameToModifierMap = new CNameToModifierMap;
01281 s_modifierToNameMap = new CModifierToNameMap;
01282 for (const KeyModifierNameMapEntry* i = kModifierNameMap;
01283 i->m_name != NULL; ++i) {
01284 (*s_nameToModifierMap)[i->m_name] = i->m_mask;
01285 (*s_modifierToNameMap)[i->m_mask] = i->m_name;
01286 }
01287 }
01288 }
01289
01290
01291
01292
01293
01294
01295 bool
01296 CKeyMap::KeyItem::operator==(const KeyItem& x) const
01297 {
01298 return (m_id == x.m_id &&
01299 m_group == x.m_group &&
01300 m_button == x.m_button &&
01301 m_required == x.m_required &&
01302 m_sensitive == x.m_sensitive &&
01303 m_generates == x.m_generates &&
01304 m_dead == x.m_dead &&
01305 m_lock == x.m_lock &&
01306 m_client == x.m_client);
01307 }
01308
01309
01310
01311
01312
01313
01314 CKeyMap::Keystroke::Keystroke(KeyButton button,
01315 bool press, bool repeat, UInt32 data) :
01316 m_type(kButton)
01317 {
01318 m_data.m_button.m_button = button;
01319 m_data.m_button.m_press = press;
01320 m_data.m_button.m_repeat = repeat;
01321 m_data.m_button.m_client = data;
01322 }
01323
01324 CKeyMap::Keystroke::Keystroke(SInt32 group, bool absolute, bool restore) :
01325 m_type(kGroup)
01326 {
01327 m_data.m_group.m_group = group;
01328 m_data.m_group.m_absolute = absolute;
01329 m_data.m_group.m_restore = restore;
01330 }