aboutsummaryrefslogtreecommitdiff
path: root/backends/keymapper/keymap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'backends/keymapper/keymap.cpp')
-rw-r--r--backends/keymapper/keymap.cpp289
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