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