diff options
author | Stephen Kennedy | 2008-08-07 16:38:39 +0000 |
---|---|---|
committer | Stephen Kennedy | 2008-08-07 16:38:39 +0000 |
commit | 2645ca48ad9bc219b43ab88cc5b071952297a992 (patch) | |
tree | d1383869820354fb99560d630c0d694535d5ad61 /backends/keymapper | |
parent | 66e4e3ec1a038bc653bb1c04893c39033ac3fb62 (diff) | |
download | scummvm-rg350-2645ca48ad9bc219b43ab88cc5b071952297a992.tar.gz scummvm-rg350-2645ca48ad9bc219b43ab88cc5b071952297a992.tar.bz2 scummvm-rg350-2645ca48ad9bc219b43ab88cc5b071952297a992.zip |
* Moved VK code into backends/vkeybd
* Moved Keymapper code into backends/keymapper
svn-id: r33681
Diffstat (limited to 'backends/keymapper')
-rw-r--r-- | backends/keymapper/action.cpp | 60 | ||||
-rw-r--r-- | backends/keymapper/action.h | 115 | ||||
-rw-r--r-- | backends/keymapper/hardware-key.h | 129 | ||||
-rw-r--r-- | backends/keymapper/keymap-manager.cpp | 168 | ||||
-rw-r--r-- | backends/keymapper/keymap-manager.h | 97 | ||||
-rw-r--r-- | backends/keymapper/keymap.cpp | 164 | ||||
-rw-r--r-- | backends/keymapper/keymap.h | 135 | ||||
-rw-r--r-- | backends/keymapper/keymapper.cpp | 146 | ||||
-rw-r--r-- | backends/keymapper/keymapper.h | 131 |
9 files changed, 1145 insertions, 0 deletions
diff --git a/backends/keymapper/action.cpp b/backends/keymapper/action.cpp new file mode 100644 index 0000000000..eefd482de7 --- /dev/null +++ b/backends/keymapper/action.cpp @@ -0,0 +1,60 @@ +/* ScummVM - Graphic Adventure Engine +* +* ScummVM is the legal property of its developers, whose names +* are too numerous to list here. Please refer to the COPYRIGHT +* file distributed with this source distribution. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* $URL$ +* $Id$ +* +*/ + +#include "backends/keymapper/action.h" +#include "backends/keymapper/keymap.h" + +namespace Common { + +Action::Action(int32 i, String des, + ActionCategory cat, ActionType typ, + int pri, int grp, int flg) { + id = i; + description = des; + category = cat; + type = typ; + priority = pri; + group = grp; + flags = flg; + _hwKey = 0; + _parent = 0; +} + +void Action::setParent(Keymap *parent) { + _parent = parent; +} + +void Action::mapKey(const HardwareKey *key) { + assert(_parent); + if (_hwKey) _parent->unregisterMapping(this); + _hwKey = key; + if (_hwKey) _parent->registerMapping(this, key); +} + +const HardwareKey *Action::getMappedKey() const { + return _hwKey; +} + +} // end of namespace Common diff --git a/backends/keymapper/action.h b/backends/keymapper/action.h new file mode 100644 index 0000000000..d9ecb873b3 --- /dev/null +++ b/backends/keymapper/action.h @@ -0,0 +1,115 @@ +/* ScummVM - Graphic Adventure Engine +* +* ScummVM is the legal property of its developers, whose names +* are too numerous to list here. Please refer to the COPYRIGHT +* file distributed with this source distribution. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* $URL$ +* $Id$ +* +*/ + +#ifndef COMMON_ACTION +#define COMMON_ACTION + +#include "common/events.h" +#include "common/func.h" +#include "common/list.h" +#include "common/str.h" + +namespace Common { + +struct HardwareKey; +class Keymap; + + +enum ActionType { + kGenericActionType, + + // common actions + kDirectionUpAction, + kDirectionDownAction, + kDirectionLeftAction, + kDirectionRightAction, + kLeftClickAction, + kRightClickAction, + kSaveAction, + kMenuAction, + kQuitAction, + kVirtualKeyboardAction, + kKeyRemapAction, + kVolumeUpAction, + kVolumeDownAction, + + + kActionTypeMax +}; + +enum ActionCategory { + kGenericActionCategory, + // classes of action - probably need to be slightly more specific than this + kInGameAction, // effects the actual gameplay + kSystemAction, //show a menu / change volume / etc + + kActionCategoryMax +}; + +struct Action { + /** unique id used for saving/loading to config */ + int32 id; + /** Human readable description */ + String description; + + /** Events to be sent when mapped key is pressed */ + List<Event> events; + ActionCategory category; + ActionType type; + int priority; + int group; + int flags; + +private: + /** Hardware key that is mapped to this Action */ + const HardwareKey *_hwKey; + Keymap *_parent; + +public: + Action( int32 id, + String des = "", + ActionCategory cat = kGenericActionCategory, + ActionType typ = kGenericActionType, + int pri = 0, int grp = 0, int flg = 0 ); + + void addEvent(const Event &evt) { events.push_back(evt); } + void setParent(Keymap *parent); + void mapKey(const HardwareKey *key); + const HardwareKey *getMappedKey() const; + +}; + +struct ActionPriorityComp : public BinaryFunction<Action, Action, bool> { + bool operator()(const Action *x, const Action *y) const { + return x->priority > y->priority; + } + bool operator()(const Action &x, const Action &y) const { + return x.priority > y.priority; + } +}; + +} // end of namespace Common + +#endif diff --git a/backends/keymapper/hardware-key.h b/backends/keymapper/hardware-key.h new file mode 100644 index 0000000000..40fb2a0cbd --- /dev/null +++ b/backends/keymapper/hardware-key.h @@ -0,0 +1,129 @@ +/* ScummVM - Graphic Adventure Engine +* +* ScummVM is the legal property of its developers, whose names +* are too numerous to list here. Please refer to the COPYRIGHT +* file distributed with this source distribution. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* $URL$ +* $Id$ +* +*/ + +#ifndef COMMON_HARDWAREKEY +#define COMMON_HARDWAREKEY + +#include "backends/keymapper/action.h" + +namespace Common { + +/** +* Describes an available hardware key +*/ +struct HardwareKey { + /** unique id used for saving/loading to config */ + int32 id; + /** Human readable description */ + String description; + /** + * The KeyState that is generated by the back-end + * when this hardware key is pressed. + */ + KeyState key; + + ActionCategory preferredCategory; + ActionType preferredType; + int16 group; + + HardwareKey(int32 i, KeyState ks = KeyState(), String des = "", + ActionCategory cat = kGenericActionCategory, + ActionType ty = kGenericActionType, int gr = 0) { + id = i; + key = ks; + description = des; + preferredCategory = cat; + preferredType = ty; + group = gr; + } +}; + + +/** + * Simple class to encapsulate a device's set of HardwareKeys. + * Each device should extend this and call addHardwareKey a number of times + * in its constructor to define the device's available keys. + */ +class HardwareKeySet { +public: + + HardwareKeySet() {} + virtual ~HardwareKeySet() { + List<HardwareKey*>::iterator it; + for (it = _keys.begin(); it != _keys.end(); it++) + delete *it; + } + + void addHardwareKey(HardwareKey *key) { + checkForKey(key); + _keys.push_back(key); + } + + const HardwareKey *findHardwareKey(int32 id) const { + List<HardwareKey*>::iterator it; + for (it = _keys.begin(); it != _keys.end(); it++) { + if ((*it)->id == id) + return (*it); + } + return 0; + } + + const HardwareKey *findHardwareKey(const KeyState& keystate) const { + List<HardwareKey*>::iterator it; + for (it = _keys.begin(); it != _keys.end(); it++) { + if ((*it)->key == keystate) + return (*it); + } + return 0; + } + + List<HardwareKey*> getHardwareKeys() const { + return _keys; + } + + uint count() const { + return _keys.size(); + } + + +private: + + void checkForKey(HardwareKey *key) { + List<HardwareKey*>::iterator it; + for (it = _keys.begin(); it != _keys.end(); it++) { + if ((*it)->id == key->id) + error("Error adding HardwareKey '%s' - id of %d already in use!", key->description.c_str(), key->id); + else if ((*it)->key == key->key) + error("Error adding HardwareKey '%s' - key already in use!", key->description.c_str()); + } + } + + List<HardwareKey*> _keys; +}; + + +} // end of namespace Common + +#endif diff --git a/backends/keymapper/keymap-manager.cpp b/backends/keymapper/keymap-manager.cpp new file mode 100644 index 0000000000..c8b4420289 --- /dev/null +++ b/backends/keymapper/keymap-manager.cpp @@ -0,0 +1,168 @@ +/* ScummVM - Graphic Adventure Engine +* +* ScummVM is the legal property of its developers, whose names +* are too numerous to list here. Please refer to the COPYRIGHT +* file distributed with this source distribution. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* $URL$ +* $Id$ +* +*/ + +#include "backends/keymapper/keymap-manager.h" +#include "common/algorithm.h" + +namespace Common { + +void KeymapManager::Domain::setDefaultKeymap(Keymap *map) { + delete _defaultKeymap; + _defaultKeymap = map; +} + +void KeymapManager::Domain::addKeymap(const String& name, Keymap *map) { + KeymapMap::iterator it = _keymaps.find(name); + if (it != _keymaps.end()) + delete _keymaps[name]; + _keymaps[name] = map; +} + +void KeymapManager::Domain::deleteAllKeyMaps() { + KeymapMap::iterator it; + for (it = _keymaps.begin(); it != _keymaps.end(); it++) { + //it->_value->saveMappings(_configDomain, it->_key); + delete it->_value; + } + _keymaps.clear(); + if (_defaultKeymap) { + //_defaultKeymap->saveMappings(_configDomain, "default"); + delete _defaultKeymap; + } +} + +Keymap *KeymapManager::Domain::getDefaultKeymap() { + return _defaultKeymap; +} + +Keymap *KeymapManager::Domain::getKeymap(const String& name) { + KeymapMap::iterator it = _keymaps.find(name); + if (it != _keymaps.end()) + return it->_value; + else + return 0; +} + +KeymapManager::KeymapManager() { + _hardwareKeys = 0; + _globalDomain.setConfigDomain(ConfMan.getDomain(ConfigManager::kApplicationDomain)); +} + +KeymapManager::~KeymapManager() { + delete _hardwareKeys; +} + +void KeymapManager::registerHardwareKeySet(HardwareKeySet *keys) { + if (_hardwareKeys) + error("Hardware key set already registered!"); + _hardwareKeys = keys; +} + +void KeymapManager::registerDefaultGlobalKeymap(Keymap *map) { + ConfigManager::Domain *dom = ConfMan.getDomain(ConfigManager::kApplicationDomain); + assert(dom); + + initKeymap(dom, "default", map); + _globalDomain.setDefaultKeymap(map); +} + +void KeymapManager::registerGlobalKeymap(const String& name, Keymap *map) { + ConfigManager::Domain *dom = ConfMan.getDomain(ConfigManager::kApplicationDomain); + assert(dom); + + initKeymap(dom, name, map); + _globalDomain.addKeymap(name, map); +} + +void KeymapManager::refreshGameDomain() { + if (_gameDomain.getConfigDomain() != ConfMan.getActiveDomain()) { + _gameDomain.deleteAllKeyMaps(); + _gameDomain.setConfigDomain(ConfMan.getActiveDomain()); + } +} + +void KeymapManager::registerDefaultGameKeymap(Keymap *map) { + refreshGameDomain(); + initKeymap(_gameDomain.getConfigDomain(), "default", map); + _gameDomain.setDefaultKeymap(map); +} + +void KeymapManager::registerGameKeymap(const String& name, Keymap *map) { + refreshGameDomain(); + initKeymap(_gameDomain.getConfigDomain(), name, map); + _gameDomain.addKeymap(name, map); +} + +void KeymapManager::initKeymap(ConfigManager::Domain *domain, + const String& name, + Keymap *map) { + map->loadMappings(domain, name, _hardwareKeys); + if (map->isComplete(_hardwareKeys) == false) + automaticMap(map); +} + +void KeymapManager::automaticMap(Keymap *map) { + List<Action*> actions(map->getActions()), unmapped; + List<Action*>::iterator actIt; + List<HardwareKey*> keys = _hardwareKeys->getHardwareKeys(); + List<HardwareKey*>::iterator keyIt, selectedKey; + + // sort by priority + ActionPriorityComp priorityComp; + sort(actions.begin(), actions.end(), priorityComp); + + for (actIt = actions.begin(); actIt != actions.end(); actIt++) { + selectedKey = keys.end(); + Action *act = *actIt; + for (keyIt = keys.begin(); keyIt != keys.end(); keyIt++) { + if ((*keyIt)->preferredType == act->type) { + selectedKey = keyIt; + break; + } else if ((*keyIt)->preferredCategory == act->category && selectedKey == keys.end()) { + selectedKey = keyIt; + } + } + if (selectedKey != keys.end()) { + act->mapKey(*selectedKey); + keys.erase(selectedKey); + } else + unmapped.push_back(act); + } + + actIt = unmapped.begin(); + keyIt = keys.begin(); + while (actIt != unmapped.end() && keyIt != keys.end()) + (*actIt)->mapKey(*keyIt); + +} + +Keymap *KeymapManager::getKeymap(const String& name) { + Keymap *keymap = _gameDomain.getKeymap(name); + if (!keymap) + _globalDomain.getKeymap(name); + return keymap; +} + +} // end of namespace Common diff --git a/backends/keymapper/keymap-manager.h b/backends/keymapper/keymap-manager.h new file mode 100644 index 0000000000..171da3ac5e --- /dev/null +++ b/backends/keymapper/keymap-manager.h @@ -0,0 +1,97 @@ +/* ScummVM - Graphic Adventure Engine +* +* ScummVM is the legal property of its developers, whose names +* are too numerous to list here. Please refer to the COPYRIGHT +* file distributed with this source distribution. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* $URL$ +* $Id$ +* +*/ + +#ifndef COMMON_KEYMAP_MANAGER +#define COMMON_KEYMAP_MANAGER + +#include "backends/keymapper/hardware-key.h" +#include "backends/keymapper/keymap.h" +#include "common/hash-str.h" +#include "common/hashmap.h" + +namespace Common { + +class KeymapManager { +public: + + class Domain { + public: + Domain() : _defaultKeymap(0), _configDomain(0) {} + ~Domain() { + deleteAllKeyMaps(); + } + + void setConfigDomain(ConfigManager::Domain *confDom) { + _configDomain = confDom; + } + ConfigManager::Domain *getConfigDomain() { + return _configDomain; + } + + void setDefaultKeymap(Keymap *map); + void addKeymap(const String& name, Keymap *map); + + void deleteAllKeyMaps(); + + Keymap *getDefaultKeymap(); + Keymap *getKeymap(const String& name); + + private: + typedef HashMap<String, Keymap*, + IgnoreCase_Hash, IgnoreCase_EqualTo> KeymapMap; + + ConfigManager::Domain *_configDomain; + Keymap *_defaultKeymap; + KeymapMap _keymaps; + }; + + KeymapManager(); + ~KeymapManager(); + + void registerHardwareKeySet(HardwareKeySet *keys); + + void registerDefaultGlobalKeymap(Keymap *map); + void registerGlobalKeymap(const String& name, Keymap *map); + + void refreshGameDomain(); + void registerDefaultGameKeymap(Keymap *map); + void registerGameKeymap(const String& name, Keymap *map); + + Keymap *getKeymap(const String& name); + +private: + + void initKeymap(ConfigManager::Domain *domain, const String& name, Keymap *keymap); + void automaticMap(Keymap *map); + + Domain _globalDomain; + Domain _gameDomain; + + HardwareKeySet *_hardwareKeys; +}; + +} // end of namespace Common + +#endif diff --git a/backends/keymapper/keymap.cpp b/backends/keymapper/keymap.cpp new file mode 100644 index 0000000000..3f190dcd48 --- /dev/null +++ b/backends/keymapper/keymap.cpp @@ -0,0 +1,164 @@ +/* ScummVM - Graphic Adventure Engine +* +* ScummVM is the legal property of its developers, whose names +* are too numerous to list here. Please refer to the COPYRIGHT +* file distributed with this source distribution. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* $URL$ +* $Id$ +* +*/ + +#include "backends/keymapper/keymap.h" +#include "backends/keymapper/hardware-key.h" + +namespace Common { + +Keymap::Keymap(const Keymap& km) : _actions(km._actions), _keymap() { + List<Action*>::iterator it; + for (it = _actions.begin(); it != _actions.end(); it++) { + const HardwareKey *hwKey = (*it)->getMappedKey(); + if (hwKey) { + _keymap[hwKey->key] = *it; + } + } +} + +void Keymap::addAction(Action *action) { + if (findAction(action->id)) + error("Action with id %d already in KeyMap!", action->id); + action->setParent(this); + _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 an action then un-map it + if (it != _keymap.end()) + it->_value->mapKey(0); + + _keymap[hwKey->key] = action; +} + +void Keymap::unregisterMapping(Action *action) { + const HardwareKey *hwKey = action->getMappedKey(); + if (hwKey) + _keymap[hwKey->key] = 0; +} + +Action *Keymap::getAction(int32 id) { + return findAction(id); +} + +Action *Keymap::findAction(int32 id) { + List<Action*>::iterator it; + for (it = _actions.begin(); it != _actions.end(); it++) { + if ((*it)->id == id) + return *it; + } + return 0; +} + +const Action *Keymap::findAction(int32 id) const { + List<Action*>::const_iterator it; + for (it = _actions.begin(); it != _actions.end(); it++) { + if ((*it)->id == id) + return *it; + } + return 0; +} + +Action *Keymap::getMappedAction(const KeyState& ks) const { + HashMap<KeyState, Action*>::iterator it; + it = _keymap.find(ks); + if (it == _keymap.end()) + return 0; + else + return it->_value; +} + +void Keymap::loadMappings(ConfigManager::Domain *domain, const String& name, const HardwareKeySet *hwKeys) { + ConfigManager::Domain::iterator it; + String prefix = "km_" + name + "_"; + for (it = domain->begin(); it != domain->end(); it++) { + const String& key = it->_key; + if (!key.hasPrefix(prefix.c_str())) + continue; + + // parse Action ID + const char *actionIdStart = key.c_str() + prefix.size(); + char *err; + int32 actionId = (int32) strtol(actionIdStart, &err, 0); + if (err == actionIdStart) { + warning("'%s' is not a valid Action ID", err); + continue; + } + Action *ua = getAction(actionId); + if (!ua) { + warning("'%s' keymap does not contain Action with ID %d", + name.c_str(), (int)actionId); + continue; + } + + // parse HardwareKey ID + int32 hwKeyId = (int32) strtol(it->_value.c_str(), &err, 0); + if (err == it->_value.c_str()) { + warning("'%s' is not a valid HardwareKey ID", err); + continue; + } + const HardwareKey *hwKey = hwKeys->findHardwareKey(hwKeyId); + if (!hwKey) { + warning("HardwareKey with ID %d not known", (int)hwKeyId); + continue; + } + + ua->mapKey(hwKey); + } +} + +void Keymap::saveMappings(ConfigManager::Domain *domain, const String& name) { + if (!domain) return; + List<Action*>::const_iterator it; + char buf[11]; + for (it = _actions.begin(); it != _actions.end(); it++) { + String key("km_"); + sprintf(buf, "%d", (*it)->id); + key += name + "_" + buf; + if ((*it)->getMappedKey()) + sprintf(buf, "%d", (*it)->getMappedKey()->id); + else + strcpy(buf, ""); + domain->setVal(key, buf); + } +} + +bool Keymap::isComplete(const HardwareKeySet *hwKeys) { + List<Action*>::iterator it; + bool allMapped = true; + uint numberMapped = 0; + for (it = _actions.begin(); it != _actions.end(); it++) { + if ((*it)->getMappedKey()) { + numberMapped++; + } else { + allMapped = false; + } + } + return allMapped || (numberMapped == hwKeys->count()); +} + +} // end of namespace Common diff --git a/backends/keymapper/keymap.h b/backends/keymapper/keymap.h new file mode 100644 index 0000000000..21904397a1 --- /dev/null +++ b/backends/keymapper/keymap.h @@ -0,0 +1,135 @@ +/* ScummVM - Graphic Adventure Engine +* +* ScummVM is the legal property of its developers, whose names +* are too numerous to list here. Please refer to the COPYRIGHT +* file distributed with this source distribution. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* $URL$ +* $Id$ +* +*/ + +#ifndef COMMON_KEYMAP +#define COMMON_KEYMAP + +#include "common/config-manager.h" +#include "common/func.h" +#include "common/hashmap.h" +#include "common/keyboard.h" +#include "common/list.h" +#include "backends/keymapper/action.h" + +namespace Common { + +struct HardwareKey; +class HardwareKeySet; + +/** + * Hash function for KeyState + */ +template<> struct Hash<KeyState> + : public UnaryFunction<KeyState, uint> { + + uint operator()(const KeyState &val) const { + return (uint)(val.keycode * (val.flags << 1)); + } +}; + +class Keymap { +public: + Keymap() {} + Keymap(const Keymap& km); + +public: + /** + * Adds a new Action to this Map, + * adding it at the back of the internal array + * @param action the Action to add + */ + void addAction(Action *action); + + /** + * Retrieves the Action with the given id + * @param id id of Action to retrieve + * @return Pointer to the Action or 0 if not found + */ + Action *getAction(int32 id); + + /** + * Get a read-only array of all the Actions contained in this Keymap + */ + const List<Action*>& getActions() const { return _actions; } + + /** + * Find the Action that a key is mapped to + * @param key the key that is mapped to the required Action + * @return a pointer to the Action or 0 if no + */ + Action *getMappedAction(const KeyState& ks) const; + + /** + * Load this keymap's mappings from the given config domain and hardware key set + * @param domain config domain to load keymap from + * @param name name of the keymap to load + * @param hwKeys the set to retrieve hardware key pointers from + */ + void loadMappings(ConfigManager::Domain *domain, const String& name, const HardwareKeySet *hwKeys); + + /** + * Save this keymap's mappings to the given config domain + * @param domain config domain to save keymap to + * @param name name to save the keymap under + */ + void saveMappings(ConfigManager::Domain *domain, const String& name); + + /** + * Returns true if all UserAction's in Keymap are mapped, or, + * all HardwareKey's from the given set have been used up. + */ + bool isComplete(const HardwareKeySet *hwKeys); + +private: + friend struct Action; + /** + * Registers a HardwareKey to the given Action + * @param action Action in this Keymap + * @param key pointer to HardwareKey to map + * @see Action::mapKey + */ + void registerMapping(Action *action, const HardwareKey *key); + + /** + * Unregisters a HardwareKey from the given Action (if one is mapped) + * @param action Action in this Keymap + * @see Action::mapKey + */ + void unregisterMapping(Action *action); + + Action *findAction(int32 id); + const Action *findAction(int32 id) const; + + void internalMapKey(Action *action, HardwareKey *hwKey); + + List<Action*> _actions; + HashMap<KeyState, Action*> _keymap; + +}; + + +} // end of namespace Common + +#endif diff --git a/backends/keymapper/keymapper.cpp b/backends/keymapper/keymapper.cpp new file mode 100644 index 0000000000..fb1f72e84e --- /dev/null +++ b/backends/keymapper/keymapper.cpp @@ -0,0 +1,146 @@ +/* ScummVM - Graphic Adventure Engine +* +* ScummVM is the legal property of its developers, whose names +* are too numerous to list here. Please refer to the COPYRIGHT +* file distributed with this source distribution. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* $URL$ +* $Id$ +* +*/ + +#include "backends/keymapper/keymapper.h" +#include "common/config-manager.h" +namespace Common { + +Keymapper::Keymapper(EventManager *evtMgr) { + _eventMan = evtMgr; + _keymapMan = new KeymapManager(); +} + +Keymapper::~Keymapper() { + delete _keymapMan; +} + +void Keymapper::registerHardwareKeySet(HardwareKeySet *keys) { + _keymapMan->registerHardwareKeySet(keys); +} + +void Keymapper::addGlobalKeymap(const String& name, Keymap *keymap) { + _keymapMan->registerGlobalKeymap(name, keymap); +} + +void Keymapper::setDefaultGlobalKeymap(Keymap *keymap) { + _keymapMan->registerDefaultGlobalKeymap(keymap); + pushKeymap(keymap, false); +} + +void Keymapper::addGameKeymap(const String& name, Keymap *keymap) { + if (ConfMan.getActiveDomain() == 0) + error("Call to Keymapper::initGame when no game loaded"); + + _keymapMan->registerGameKeymap(name, keymap); +} + +void Keymapper::setDefaultGameKeymap(Keymap *keymap) { + if (ConfMan.getActiveDomain() == 0) + error("Call to Keymapper::initGame when no game loaded"); + + _keymapMan->registerDefaultGameKeymap(keymap); + pushKeymap(keymap, true); +} + +bool Keymapper::pushKeymap(const String& name, bool inherit) { + Keymap *newMap = _keymapMan->getKeymap(name); + if (!newMap) { + warning("Keymap '%s' not registered", name.c_str()); + return false; + } + pushKeymap(newMap, inherit); + return true; +} + +void Keymapper::pushKeymap(Keymap *newMap, bool inherit) { + MapRecord mr; + mr.inherit = inherit; + mr.keymap = newMap; + _activeMaps.push(mr); +} + +void Keymapper::popKeymap() { + if (!_activeMaps.empty()) + _activeMaps.pop(); +} + +bool Keymapper::mapKeyDown(const KeyState& key) { + return mapKey(key, true); +} + +bool Keymapper::mapKeyUp(const KeyState& key) { + return mapKey(key, false); +} + +bool Keymapper::mapKey(const KeyState& key, bool isKeyDown) { + if (_activeMaps.empty()) return false; + + Action *action = 0; + for (int i = _activeMaps.size() - 1; !action && i >= 0; i++) { + MapRecord mr = _activeMaps[i]; + action = mr.keymap->getMappedAction(key); + if (mr.inherit == false) break; + } + if (!action) return false; + + List<Event>::iterator it; + for (it = action->events.begin(); it != action->events.end(); it++) { + Event evt = *it; + bool pushEvent = true; + switch (evt.type) { + case EVENT_KEYDOWN: + if (!isKeyDown) evt.type = EVENT_KEYUP; + break; + case EVENT_KEYUP: + if (isKeyDown) evt.type = EVENT_KEYDOWN; + break; + case EVENT_LBUTTONDOWN: + if (!isKeyDown) evt.type = EVENT_LBUTTONUP; + break; + case EVENT_LBUTTONUP: + if (isKeyDown) evt.type = EVENT_LBUTTONDOWN; + break; + case EVENT_RBUTTONDOWN: + if (!isKeyDown) evt.type = EVENT_RBUTTONUP; + break; + case EVENT_RBUTTONUP: + if (isKeyDown) evt.type = EVENT_RBUTTONDOWN; + break; + case EVENT_MBUTTONDOWN: + if (!isKeyDown) evt.type = EVENT_MBUTTONUP; + break; + case EVENT_MBUTTONUP: + if (isKeyDown) evt.type = EVENT_MBUTTONDOWN; + break; + default: + // don't deliver other events on key up + if (!isKeyDown) pushEvent = false; + } + if (pushEvent) _eventMan->pushEvent(evt); + } + return true; +} + +} // end of namespace Common diff --git a/backends/keymapper/keymapper.h b/backends/keymapper/keymapper.h new file mode 100644 index 0000000000..1052903b77 --- /dev/null +++ b/backends/keymapper/keymapper.h @@ -0,0 +1,131 @@ +/* ScummVM - Graphic Adventure Engine +* +* ScummVM is the legal property of its developers, whose names +* are too numerous to list here. Please refer to the COPYRIGHT +* file distributed with this source distribution. +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* $URL$ +* $Id$ +* +*/ + +#ifndef COMMON_KEYMAPPER +#define COMMON_KEYMAPPER + +#include "common/events.h" +#include "common/list.h" +#include "common/stack.h" +#include "backends/keymapper/hardware-key.h" +#include "backends/keymapper/keymap.h" +#include "backends/keymapper/keymap-manager.h" + +namespace Common { + +class Keymapper { +public: + + Keymapper(EventManager *eventMan); + ~Keymapper(); + + /** + * Registers a HardwareKeySet with the Keymapper + * @note should only be called once (during backend initialisation) + */ + void registerHardwareKeySet(HardwareKeySet *keys); + + + /** + * Add a general keymap to the global domain. + * If a saved key setup exists for it in the ini file it will be used. + * Else, the key setup will be automatically mapped. + */ + void addGlobalKeymap(const String& name, Keymap *keymap); + + /** + * Sets the default keymap for the global domain. + */ + void setDefaultGlobalKeymap(Keymap *keymap); + + /** + * Add a general keymap to the game domain. + * @see addGlobalKeyMap + * @note initGame() should be called before any game keymaps are added. + */ + void addGameKeymap(const String& name, Keymap *keymap); + + /** + * Sets the default keymap for the game domain. + */ + void setDefaultGameKeymap(Keymap *keymap); + + /** + * Push a new keymap to the top of the active stack, activating it for use. + * @param name name of the keymap to push + * @param inherit if true + * @return true if successful + */ + bool pushKeymap(const String& name, bool inherit = false); + + /** + * Pop the active keymap off the stack. + */ + void popKeymap(); + + /** + * @brief Map a key press event. + * If the active keymap contains a Action mapped to the given key, then + * the Action's events are pushed into the EventManager's event queue. + * @param key key that was pressed + * @param isKeyDown true for key down, false for key up + * @return true if key was mapped + */ + bool mapKey(const KeyState& key, bool isKeyDown); + + /** + * @brief Map a key down event. + * @see mapKey + */ + bool mapKeyDown(const KeyState& key); + + /** + * @brief Map a key up event. + * @see mapKey + */ + bool mapKeyUp(const KeyState& key); + +private: + + void pushKeymap(Keymap *newMap, bool inherit); + + typedef List<HardwareKey*>::iterator Iterator; + + EventManager *_eventMan; + KeymapManager *_keymapMan; + + + struct MapRecord { + Keymap* keymap; + bool inherit; + }; + + Stack<MapRecord> _activeMaps; + +}; + +} // end of namespace Common + +#endif |