diff options
Diffstat (limited to 'backends/keymapper/keymap.cpp')
-rw-r--r-- | backends/keymapper/keymap.cpp | 289 |
1 files changed, 93 insertions, 196 deletions
diff --git a/backends/keymapper/keymap.cpp b/backends/keymapper/keymap.cpp index d2c9b9b572..e95dd6afb5 100644 --- a/backends/keymapper/keymap.cpp +++ b/backends/keymapper/keymap.cpp @@ -24,26 +24,32 @@ #ifdef ENABLE_KEYMAPPER -#include "backends/keymapper/hardware-key.h" +#include "common/system.h" + +#include "backends/keymapper/hardware-input.h" +#include "backends/keymapper/keymapper-defaults.h" #define KEYMAP_KEY_PREFIX "keymap_" namespace Common { -Keymap::Keymap(const Keymap& km) : _actions(km._actions), _keymap(), _configDomain(0) { - List<Action*>::iterator it; +Keymap::Keymap(const Keymap& km) : _actions(km._actions), _keymap(), _nonkeymap(), _configDomain(0) { + List<Action *>::iterator it; for (it = _actions.begin(); it != _actions.end(); ++it) { - const HardwareKey *hwKey = (*it)->getMappedKey(); + const HardwareInput *hwInput = (*it)->getMappedInput(); - if (hwKey) { - _keymap[hwKey->key] = *it; + if (hwInput) { + if (hwInput->type == kHardwareInputTypeKeyboard) + _keymap[hwInput->key] = *it; + else if (hwInput->type == kHardwareInputTypeGeneric) + _nonkeymap[hwInput->inputCode] = *it; } } } Keymap::~Keymap() { - List<Action*>::iterator it; + List<Action *>::iterator it; for (it = _actions.begin(); it != _actions.end(); ++it) delete *it; @@ -56,24 +62,32 @@ void Keymap::addAction(Action *action) { _actions.push_back(action); } -void Keymap::registerMapping(Action *action, const HardwareKey *hwKey) { - HashMap<KeyState, Action*>::iterator it; - - it = _keymap.find(hwKey->key); - - // if key is already mapped to a different action then un-map it - if (it != _keymap.end() && action != it->_value) { - it->_value->mapKey(0); +void Keymap::registerMapping(Action *action, const HardwareInput *hwInput) { + if (hwInput->type == kHardwareInputTypeKeyboard) { + HashMap<KeyState, Action *>::iterator it = _keymap.find(hwInput->key); + // if input is already mapped to a different action then unmap it from there + if (it != _keymap.end() && action != it->_value) + it->_value->mapInput(0); + // now map it + _keymap[hwInput->key] = action; + } else if (hwInput->type == kHardwareInputTypeGeneric) { + HashMap<HardwareInputCode, Action *>::iterator it = _nonkeymap.find(hwInput->inputCode); + // if input is already mapped to a different action then unmap it from there + if (it != _nonkeymap.end() && action != it->_value) + it->_value->mapInput(0); + // now map it + _nonkeymap[hwInput->inputCode] = action; } - - _keymap[hwKey->key] = action; } void Keymap::unregisterMapping(Action *action) { - const HardwareKey *hwKey = action->getMappedKey(); + const HardwareInput *hwInput = action->getMappedInput(); - if (hwKey) { - _keymap.erase(hwKey->key); + if (hwInput) { + if (hwInput->type == kHardwareInputTypeKeyboard) + _keymap.erase(hwInput->key); + else if (hwInput->type == kHardwareInputTypeGeneric) + _nonkeymap.erase(hwInput->inputCode); } } @@ -82,7 +96,7 @@ Action *Keymap::getAction(const char *id) { } Action *Keymap::findAction(const char *id) { - List<Action*>::iterator it; + List<Action *>::iterator it; for (it = _actions.begin(); it != _actions.end(); ++it) { if (strncmp((*it)->id, id, ACTION_ID_SIZE) == 0) @@ -92,7 +106,7 @@ Action *Keymap::findAction(const char *id) { } const Action *Keymap::findAction(const char *id) const { - List<Action*>::const_iterator it; + List<Action *>::const_iterator it; for (it = _actions.begin(); it != _actions.end(); ++it) { if (strncmp((*it)->id, id, ACTION_ID_SIZE) == 0) @@ -103,7 +117,7 @@ const Action *Keymap::findAction(const char *id) const { } Action *Keymap::getMappedAction(const KeyState& ks) const { - HashMap<KeyState, Action*>::iterator it; + HashMap<KeyState, Action *>::iterator it; it = _keymap.find(ks); @@ -113,44 +127,70 @@ Action *Keymap::getMappedAction(const KeyState& ks) const { return it->_value; } +Action *Keymap::getMappedAction(const HardwareInputCode code) const { + HashMap<HardwareInputCode, Action *>::iterator it; + + it = _nonkeymap.find(code); + + if (it == _nonkeymap.end()) + return 0; + else + return it->_value; +} + void Keymap::setConfigDomain(ConfigManager::Domain *dom) { _configDomain = dom; } -void Keymap::loadMappings(const HardwareKeySet *hwKeys) { +void Keymap::loadMappings(const HardwareInputSet *hwKeys) { if (!_configDomain) return; - ConfigManager::Domain::iterator it; - String prefix = KEYMAP_KEY_PREFIX + _name + "_"; + if (_actions.empty()) + return; - for (it = _configDomain->begin(); it != _configDomain->end(); ++it) { - const String& key = it->_key; + Common::KeymapperDefaultBindings *defaults = g_system->getKeymapperDefaultBindings(); - if (!key.hasPrefix(prefix.c_str())) - continue; + HashMap<String, const HardwareInput *> mappedInputs; + List<Action*>::iterator it; + String prefix = KEYMAP_KEY_PREFIX + _name + "_"; - // parse Action ID - const char *actionId = key.c_str() + prefix.size(); - Action *ua = getAction(actionId); + for (it = _actions.begin(); it != _actions.end(); ++it) { + Action* ua = *it; + String actionId(ua->id); + String confKey = prefix + actionId; + + String hwInputId = _configDomain->getVal(confKey); + + bool defaulted = false; + // fall back to the platform-specific defaults + if (hwInputId.empty() && defaults) { + hwInputId = defaults->getDefaultBinding(_name, actionId); + if (!hwInputId.empty()) + defaulted = true; + } + // there's no mapping + if (hwInputId.empty()) + continue; - if (!ua) { - warning("'%s' keymap does not contain Action with ID %s", - _name.c_str(), actionId); - _configDomain->erase(key); + const HardwareInput *hwInput = hwKeys->findHardwareInput(hwInputId.c_str()); + if (!hwInput) { + warning("HardwareInput with ID '%s' not known", hwInputId.c_str()); continue; } - const HardwareKey *hwKey = hwKeys->findHardwareKey(it->_value.c_str()); - - if (!hwKey) { - warning("HardwareKey with ID %s not known", it->_value.c_str()); - _configDomain->erase(key); - continue; + if (defaulted) { + if (mappedInputs.contains(hwInputId)) { + debug(1, "Action [%s] not falling back to hardcoded default value [%s] because the hardware input is in use", confKey.c_str(), hwInputId.c_str()); + continue; + } + warning("Action [%s] fell back to hardcoded default value [%s]", confKey.c_str(), hwInputId.c_str()); } - ua->mapKey(hwKey); + mappedInputs.setVal(hwInputId, hwInput); + // map the key + ua->mapInput(hwInput); } } @@ -158,7 +198,7 @@ void Keymap::saveMappings() { if (!_configDomain) return; - List<Action*>::const_iterator it; + List<Action *>::const_iterator it; String prefix = KEYMAP_KEY_PREFIX + _name + "_"; for (it = _actions.begin(); it != _actions.end(); ++it) { @@ -167,172 +207,29 @@ void Keymap::saveMappings() { actIdLen = (actIdLen > ACTION_ID_SIZE) ? ACTION_ID_SIZE : actIdLen; String actId((*it)->id, (*it)->id + actIdLen); - char hwId[HWKEY_ID_SIZE+1]; + String hwId = ""; - memset(hwId, 0, HWKEY_ID_SIZE+1); - - if ((*it)->getMappedKey()) { - memcpy(hwId, (*it)->getMappedKey()->hwKeyId, HWKEY_ID_SIZE); + if ((*it)->getMappedInput()) { + hwId = (*it)->getMappedInput()->id; } _configDomain->setVal(prefix + actId, hwId); } } -bool Keymap::isComplete(const HardwareKeySet *hwKeys) { - List<Action*>::iterator it; +bool Keymap::isComplete(const HardwareInputSet *hwInputs) { + List<Action *>::iterator it; bool allMapped = true; uint numberMapped = 0; for (it = _actions.begin(); it != _actions.end(); ++it) { - if ((*it)->getMappedKey()) { - numberMapped++; + if ((*it)->getMappedInput()) { + ++numberMapped; } else { allMapped = false; } } - return allMapped || (numberMapped == hwKeys->size()); -} - -// TODO: -// - current weakness: -// - if an action finds a key with required type but a parent action with -// higher priority is using it, that key is never used -void Keymap::automaticMapping(HardwareKeySet *hwKeys) { -#if 0 //disabling the broken automapper for now - // Create copies of action and key lists. - List<Action*> actions(_actions); - List<const HardwareKey*> keys(hwKeys->getHardwareKeys()); - - List<Action*>::iterator actIt; - List<const HardwareKey*>::iterator keyIt, selectedKey; - - // Remove actions and keys from local lists that have already been mapped. - actIt = actions.begin(); - - while (actIt != actions.end()) { - Action *act = *actIt; - const HardwareKey *key = act->getMappedKey(); - - if (key) { - keys.remove(key); - actIt = actions.erase(actIt); - } else { - ++actIt; - } - } - - // Sort remaining actions by priority. - ActionPriorityComp priorityComp; - sort(actions.begin(), actions.end(), priorityComp); - - // First mapping pass: - // - Match if a key's preferred action type is the same as the action's - // type, or vice versa. - // - Priority is given to: - // - keys that match action types over key types. - // - keys that have not been used by parent maps. - // - If a key has been used by a parent map the new action must have a - // higher priority than the parent action. - // - As soon as the number of skipped actions equals the number of keys - // remaining we stop matching. This means that the second pass will assign keys - // to these higher priority skipped actions. - uint skipped = 0; - actIt = actions.begin(); - - while (actIt != actions.end() && skipped < keys.size()) { - selectedKey = keys.end(); - int matchRank = 0; - Action *act = *actIt; - - for (keyIt = keys.begin(); keyIt != keys.end(); ++keyIt) { - if ((*keyIt)->preferredAction == act->type && act->type != kGenericActionType) { - Action *parentAct = getParentMappedAction((*keyIt)->key); - - if (!parentAct) { - selectedKey = keyIt; - break; - } else if (parentAct->priority <= act->priority && matchRank < 3) { - selectedKey = keyIt; - matchRank = 3; - } - } else if ((*keyIt)->type == act->preferredKey && act->preferredKey != kGenericKeyType && matchRank < 2) { - Action *parentAct = getParentMappedAction((*keyIt)->key); - - if (!parentAct) { - selectedKey = keyIt; - matchRank = 2; - } else if (parentAct->priority <= act->priority && matchRank < 1) { - selectedKey = keyIt; - matchRank = 1; - } - } - } - if (selectedKey != keys.end()) { - // Map action and delete action & key from local lists. - act->mapKey(*selectedKey); - keys.erase(selectedKey); - actIt = actions.erase(actIt); - } else { - // Skip action (will be mapped in next pass). - ++actIt; - ++skipped; - } - } - - // Second mapping pass: - // - Maps any remaining actions to keys - // - priority given to: - // - keys that have no parent action - // - keys whose parent action has lower priority than the new action - // - keys whose parent action has the lowest priority - // - is guaranteed to match a key if they are not all used up - for (actIt = actions.begin(); actIt != actions.end(); ++actIt) { - selectedKey = keys.end(); - - int matchRank = 0; - int lowestPriority = 0; - Action *act = *actIt; - - for (keyIt = keys.begin(); keyIt != keys.end(); ++keyIt) { - Action *parentAct = getParentMappedAction((*keyIt)->key); - - if (!parentAct) { - selectedKey = keyIt; - break; - } else if (matchRank < 2) { - if (parentAct->priority <= act->priority) { - matchRank = 2; - selectedKey = keyIt; - } else if (parentAct->priority < lowestPriority || matchRank == 0) { - matchRank = 1; - lowestPriority = parentAct->priority; - selectedKey = keyIt; - } - } - } - - if (selectedKey != keys.end()) { - act->mapKey(*selectedKey); - keys.erase(selectedKey); - } else {// no match = no keys left - break; - } - } -#endif -} - -Action *Keymap::getParentMappedAction(KeyState key) { - if (_parent) { - Action *act = _parent->getMappedAction(key); - - if (act) - return act; - else - return _parent->getParentMappedAction(key); - } else { - return 0; - } + return allMapped || (numberMapped == hwInputs->size()); } } // End of namespace Common |