diff --git a/backends/keymapper/keymap.cpp b/backends/keymapper/keymap.cpp index 8dd795a2c8f..e16143918d5 100644 --- a/backends/keymapper/keymap.cpp +++ b/backends/keymapper/keymap.cpp @@ -84,7 +84,7 @@ void Keymap::unregisterMapping(Action *action) { void Keymap::resetMapping(Action *action) { unregisterMapping(action); - const Array &hwInputIds = action->getDefaultInputMapping(); + StringArray hwInputIds = getActionDefaultMappings(action); registerMappings(action, hwInputIds); } @@ -168,28 +168,33 @@ void Keymap::setHardwareInputs(HardwareInputSet *hardwareInputSet) { _hardwareInputSet = hardwareInputSet; } -void Keymap::setBackendDefaultBindings(const Common::KeymapperDefaultBindings *backendDefaultBindings) { +void Keymap::setBackendDefaultBindings(const KeymapperDefaultBindings *backendDefaultBindings) { _backendDefaultBindings = backendDefaultBindings; } -void Keymap::registerBackendDefaultMappings() { - assert(_backendDefaultBindings); - - for (ActionArray::const_iterator it = _actions.begin(); it != _actions.end(); ++it) { - Action *action = *it; - Common::String defaultHwId = _backendDefaultBindings->getDefaultBinding(_id, action->id); - - if (!defaultHwId.empty()) { - action->addDefaultInputMapping(defaultHwId); - continue; +StringArray Keymap::getActionDefaultMappings(Action *action) { + // Backend default mappings overrides keymap default mappings, so backends can resolve mapping conflicts. + // Empty mappings are valid and mean the action should not be mapped by default. + if (_backendDefaultBindings) { + KeymapperDefaultBindings::const_iterator it = _backendDefaultBindings->findDefaultBinding(_id, action->id); + if (it != _backendDefaultBindings->end()) { + if (it->_value.empty()) { + return StringArray(); + } + return StringArray(1, it->_value); } // If no keymap-specific default mapping was found, look for a standard action binding - defaultHwId = _backendDefaultBindings->getDefaultBinding(kStandardActionsKeymapName, action->id); - if (!defaultHwId.empty()) { - action->addDefaultInputMapping(defaultHwId); + it = _backendDefaultBindings->findDefaultBinding(kStandardActionsKeymapName, action->id); + if (it != _backendDefaultBindings->end()) { + if (it->_value.empty()) { + return StringArray(); + } + return StringArray(1, it->_value); } } + + return action->getDefaultInputMapping(); } void Keymap::loadMappings() { @@ -200,10 +205,6 @@ void Keymap::loadMappings() { return; } - if (_backendDefaultBindings) { - registerBackendDefaultMappings(); - } - String prefix = KEYMAP_KEY_PREFIX + _id + "_"; _hwActionMap.clear(); @@ -211,29 +212,28 @@ void Keymap::loadMappings() { Action *action = *it; String confKey = prefix + action->id; - Array hwInputIds; + StringArray hwInputIds; if (_configDomain->contains(confKey)) { // The configuration value is a list of space separated hardware input ids StringTokenizer hwInputTokenizer = _configDomain->getVal(confKey); - String hwInputId; - while ((hwInputId = hwInputTokenizer.nextToken()) != "") { - hwInputIds.push_back(hwInputId); + while (!hwInputTokenizer.empty()) { + hwInputIds.push_back(hwInputTokenizer.nextToken()); } } else { // If the configuration key was not found, use the default mapping - hwInputIds = action->getDefaultInputMapping(); + hwInputIds = getActionDefaultMappings(action); } registerMappings(action, hwInputIds); } } -void Keymap::registerMappings(Action *action, const Array &hwInputIds) { +void Keymap::registerMappings(Action *action, const StringArray &hwInputIds) { assert(_hardwareInputSet); for (uint i = 0; i < hwInputIds.size(); i++) { - HardwareInput hwInput = _hardwareInputSet->findHardwareInput(hwInputIds[i].c_str()); + HardwareInput hwInput = _hardwareInputSet->findHardwareInput(hwInputIds[i]); if (hwInput.type == kHardwareInputTypeInvalid) { // Silently ignore unknown hardware ids because the current device may not have inputs matching the defaults @@ -256,7 +256,7 @@ void Keymap::saveMappings() { Action *action = *it; Array mappedInputs = getActionMapping(action); - if (areMappingsIdentical(mappedInputs, action->getDefaultInputMapping())) { + if (areMappingsIdentical(mappedInputs, getActionDefaultMappings(action))) { // If the current mapping is the default, don't write anything to the config manager _configDomain->erase(prefix + action->id); continue; @@ -276,24 +276,24 @@ void Keymap::saveMappings() { } } -bool Keymap::areMappingsIdentical(const Array &inputs, const StringArray &mapping) { - if (inputs.size() != mapping.size()) { - return false; - } - +bool Keymap::areMappingsIdentical(const Array &mappingsA, const StringArray &mappingsB) { // Assumes array values are not duplicated, but registerMapping and addDefaultInputMapping ensure that uint foundCount = 0; - for (uint i = 0; i < inputs.size(); i++) { - for (uint j = 0; j < mapping.size(); j++) { - if (inputs[i].id == mapping[j]) { + for (uint i = 0; i < mappingsB.size(); i++) { + // We resolve the hardware input to make sure it is not a default for some hardware we don't have currently + HardwareInput mappingB = _hardwareInputSet->findHardwareInput(mappingsB[i]); + if (mappingB.type == kHardwareInputTypeInvalid) continue; + + for (uint j = 0; j < mappingsA.size(); j++) { + if (mappingsA[j].id == mappingB.id) { foundCount++; break; } } } - return foundCount == inputs.size(); + return foundCount == mappingsA.size(); } } // End of namespace Common diff --git a/backends/keymapper/keymap.h b/backends/keymapper/keymap.h index d81cfd4d5ef..4d584a2afa2 100644 --- a/backends/keymapper/keymap.h +++ b/backends/keymapper/keymap.h @@ -126,6 +126,14 @@ public: */ const ActionArray &getActions() const { return _actions; } + /** + * Get the default input mappings for an action. + * + * Backend-specific mappings replace the default mappings + * specified when creating the keymap. + */ + StringArray getActionDefaultMappings(Action *action); + /** * Load this keymap's mappings from the config manager. * @param hwInputs the set to retrieve hardware input pointers from @@ -175,8 +183,6 @@ private: ConfigManager::Domain *_configDomain; HardwareInputSet *_hardwareInputSet; const KeymapperDefaultBindings *_backendDefaultBindings; - - void registerBackendDefaultMappings(); }; typedef Array KeymapArray; diff --git a/backends/keymapper/keymapper-defaults.h b/backends/keymapper/keymapper-defaults.h index b6d395e5154..e0395bf53b5 100644 --- a/backends/keymapper/keymapper-defaults.h +++ b/backends/keymapper/keymapper-defaults.h @@ -30,7 +30,7 @@ namespace Common { -class KeymapperDefaultBindings : HashMap { +class KeymapperDefaultBindings : public HashMap { public: /** * This sets a default hwInput for a given Keymap Action @@ -45,7 +45,9 @@ public: * @param actionId String representing Action id (Action.id) * @return String representing the HardwareInput id (HardwareInput.id) */ - String getDefaultBinding(String keymapId, String actionId) const { return getVal(keymapId + "_" + actionId); } + const_iterator findDefaultBinding(String keymapId, String actionId) const { + return find(keymapId + "_" + actionId); + } }; } //namespace Common diff --git a/backends/keymapper/keymapper.cpp b/backends/keymapper/keymapper.cpp index 649db852afd..e7d876127ce 100644 --- a/backends/keymapper/keymapper.cpp +++ b/backends/keymapper/keymapper.cpp @@ -24,6 +24,7 @@ #include "backends/keymapper/action.h" #include "backends/keymapper/hardware-input.h" +#include "backends/keymapper/keymapper-defaults.h" #include "common/system.h" @@ -35,19 +36,20 @@ static const uint32 kDelayMouseEventMillis = 50; Keymapper::Keymapper(EventManager *eventMan) : _eventMan(eventMan), - _enabled(true), - _enabledKeymapType(Keymap::kKeymapTypeGlobal), _hardwareInputs(nullptr), _backendDefaultBindings(nullptr), - _delayedEventSource(new DelayedEventSource()) { + _delayedEventSource(new DelayedEventSource()), + _enabled(true), + _enabledKeymapType(Keymap::kKeymapTypeGlobal) { _eventMan->getEventDispatcher()->registerSource(_delayedEventSource, true); } Keymapper::~Keymapper() { - delete _hardwareInputs; for (KeymapArray::iterator it = _keymaps.begin(); it != _keymaps.end(); it++) { delete *it; } + delete _backendDefaultBindings; + delete _hardwareInputs; } void Keymapper::registerHardwareInputSet(HardwareInputSet *inputs) { @@ -65,7 +67,7 @@ void Keymapper::registerHardwareInputSet(HardwareInputSet *inputs) { _hardwareInputs = inputs; } -void Keymapper::registerBackendDefaultBindings(const Common::KeymapperDefaultBindings *backendDefaultBindings) { +void Keymapper::registerBackendDefaultBindings(KeymapperDefaultBindings *backendDefaultBindings) { if (!_keymaps.empty()) error("Backend default bindings must be defined before adding keymaps"); diff --git a/backends/keymapper/keymapper.h b/backends/keymapper/keymapper.h index 3c0317e1ca0..4adee5376b3 100644 --- a/backends/keymapper/keymapper.h +++ b/backends/keymapper/keymapper.h @@ -54,13 +54,17 @@ public: /** * Registers a HardwareInputSet with the Keymapper * @note should only be called once (during backend initialisation) + * + * Transfers ownership to the Keymapper */ void registerHardwareInputSet(HardwareInputSet *inputs); /** * Registers platform-specific default mappings for keymap actions + * + * Transfers ownership to the Keymapper */ - void registerBackendDefaultBindings(const KeymapperDefaultBindings *backendDefaultBindings); + void registerBackendDefaultBindings(KeymapperDefaultBindings *backendDefaultBindings); /** * Add a keymap to the global domain. @@ -126,7 +130,7 @@ public: private: EventManager *_eventMan; HardwareInputSet *_hardwareInputs; - const KeymapperDefaultBindings *_backendDefaultBindings; + KeymapperDefaultBindings *_backendDefaultBindings; DelayedEventSource *_delayedEventSource; enum IncomingEventType { diff --git a/backends/platform/maemo/maemo.cpp b/backends/platform/maemo/maemo.cpp index 4b1ee9ed202..9231c7dfd5c 100644 --- a/backends/platform/maemo/maemo.cpp +++ b/backends/platform/maemo/maemo.cpp @@ -45,35 +45,6 @@ OSystem_SDL_Maemo::OSystem_SDL_Maemo() OSystem_SDL_Maemo::~OSystem_SDL_Maemo() { delete _eventObserver; - delete _keymapperDefaultBindings; -} - -static void registerDefaultKeyBindings(Common::KeymapperDefaultBindings *_keymapperDefaultBindings, Model _model) { - _keymapperDefaultBindings->setDefaultBinding("gui", "REMP", "HOME"); - _keymapperDefaultBindings->setDefaultBinding("global", "REMP", "HOME"); - - if (_model.hasMenuKey && _model.hasHwKeyboard) { - _keymapperDefaultBindings->setDefaultBinding("gui", "FULS", "FULLSCREEN"); - _keymapperDefaultBindings->setDefaultBinding("global", "FULS", "FULLSCREEN"); - } - - if (_model.hasHwKeyboard) { - _keymapperDefaultBindings->setDefaultBinding("gui", "VIRT", "C+ZOOMMINUS"); - _keymapperDefaultBindings->setDefaultBinding("global", "VIRT", "C+ZOOMMINUS"); - } else { - _keymapperDefaultBindings->setDefaultBinding("gui", "VIRT", "FULLSCREEN"); - _keymapperDefaultBindings->setDefaultBinding("global", "VIRT", "FULLSCREEN"); - } - - if (_model.hasMenuKey ) - _keymapperDefaultBindings->setDefaultBinding("global", "MENU", "MENU"); - else - _keymapperDefaultBindings->setDefaultBinding("global", "MENU", "S+C+M"); - - _keymapperDefaultBindings->setDefaultBinding("gui", "CLOS", "ESCAPE"); - - _keymapperDefaultBindings->setDefaultBinding("maemo", "RCLK", "ZOOMPLUS"); - _keymapperDefaultBindings->setDefaultBinding("maemo", "CLKM", "ZOOMMINUS"); } void OSystem_SDL_Maemo::init() { @@ -99,13 +70,8 @@ void OSystem_SDL_Maemo::initBackend() { if (_eventObserver == 0) _eventObserver = new MaemoSdlEventObserver((MaemoSdlEventSource *)_eventSource); - if (_keymapperDefaultBindings == 0) - _keymapperDefaultBindings = new Common::KeymapperDefaultBindings(); - _model = detectModel(); - registerDefaultKeyBindings(_keymapperDefaultBindings, _model); - // Call parent implementation of this method OSystem_POSIX::initBackend(); initObserver(); @@ -221,6 +187,38 @@ Common::KeymapArray OSystem_SDL_Maemo::getGlobalKeymaps() { return globalMaps; } +Common::KeymapperDefaultBindings *OSystem_SDL_Maemo::getKeymapperDefaultBindings() { + Common::KeymapperDefaultBindings *keymapperDefaultBindings = new Common::KeymapperDefaultBindings(); + + keymapperDefaultBindings->setDefaultBinding("gui", "REMP", "HOME"); + keymapperDefaultBindings->setDefaultBinding("global", "REMP", "HOME"); + + if (_model.hasMenuKey && _model.hasHwKeyboard) { + keymapperDefaultBindings->setDefaultBinding("gui", "FULS", "FULLSCREEN"); + keymapperDefaultBindings->setDefaultBinding("global", "FULS", "FULLSCREEN"); + } + + if (_model.hasHwKeyboard) { + keymapperDefaultBindings->setDefaultBinding("gui", "VIRT", "C+ZOOMMINUS"); + keymapperDefaultBindings->setDefaultBinding("global", "VIRT", "C+ZOOMMINUS"); + } else { + keymapperDefaultBindings->setDefaultBinding("gui", "VIRT", "FULLSCREEN"); + keymapperDefaultBindings->setDefaultBinding("global", "VIRT", "FULLSCREEN"); + } + + if (_model.hasMenuKey ) + keymapperDefaultBindings->setDefaultBinding("global", "MENU", "MENU"); + else + keymapperDefaultBindings->setDefaultBinding("global", "MENU", "S+C+M"); + + keymapperDefaultBindings->setDefaultBinding("gui", "CLOS", "ESCAPE"); + + keymapperDefaultBindings->setDefaultBinding("maemo", "RCLK", "ZOOMPLUS"); + keymapperDefaultBindings->setDefaultBinding("maemo", "CLKM", "ZOOMMINUS"); + + return keymapperDefaultBindings; +} + void OSystem_SDL_Maemo::initObserver() { assert(_eventManager); _eventManager->getEventDispatcher()->registerObserver(_eventObserver, 10, false); diff --git a/backends/platform/maemo/maemo.h b/backends/platform/maemo/maemo.h index b565a68ea44..91ca084357e 100644 --- a/backends/platform/maemo/maemo.h +++ b/backends/platform/maemo/maemo.h @@ -43,7 +43,7 @@ public: virtual void setWindowCaption(const char *caption); virtual Common::HardwareInputSet *getHardwareInputSet(); Common::KeymapArray getGlobalKeymaps() override; - virtual Common::KeymapperDefaultBindings *getKeymapperDefaultBindings() { return _keymapperDefaultBindings; } + Common::KeymapperDefaultBindings *getKeymapperDefaultBindings() override; Model getModel() { return _model; } @@ -54,7 +54,6 @@ private: const Model detectModel(); Model _model; MaemoSdlEventObserver *_eventObserver; - Common::KeymapperDefaultBindings *_keymapperDefaultBindings; }; } // namespace Maemo diff --git a/base/main.cpp b/base/main.cpp index d149ed57c92..8a4d73a339c 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -361,7 +361,7 @@ static void setupKeymapper(OSystem &system) { // Query the backend for hardware keys and default bindings and register them HardwareInputSet *inputSet = system.getHardwareInputSet(); - const KeymapperDefaultBindings *backendDefaultBindings = system.getKeymapperDefaultBindings(); + KeymapperDefaultBindings *backendDefaultBindings = system.getKeymapperDefaultBindings(); mapper->registerHardwareInputSet(inputSet); mapper->registerBackendDefaultBindings(backendDefaultBindings);