From 57b13141af10c5e0773c2e1606daca8e08410ed5 Mon Sep 17 00:00:00 2001 From: Stephen Kennedy Date: Wed, 6 Aug 2008 14:21:05 +0000 Subject: Keymapper WIP: * Implemented stack-based active map in Keymapper * Started proper testing by adding code to OSystem_SDL to set up simple HardwareKeySet and Keymap svn-id: r33660 --- backends/common/action.cpp | 14 ++++--- backends/common/action.h | 21 ++++++---- backends/common/hardware-key.h | 23 +++++----- backends/common/keymap-manager.cpp | 29 ++++++++----- backends/common/keymap-manager.h | 5 ++- backends/common/keymapper.cpp | 67 +++++++++++++++++++++++------- backends/common/keymapper.h | 58 ++++++++++++++++++-------- backends/events/default/default-events.cpp | 7 ++-- backends/events/default/default-events.h | 4 +- backends/platform/sdl/events.cpp | 34 +++++++++++++++ backends/platform/sdl/sdl.cpp | 3 ++ backends/platform/sdl/sdl.h | 3 ++ 12 files changed, 195 insertions(+), 73 deletions(-) (limited to 'backends') diff --git a/backends/common/action.cpp b/backends/common/action.cpp index d6cb820b73..49d63fafd4 100644 --- a/backends/common/action.cpp +++ b/backends/common/action.cpp @@ -28,14 +28,16 @@ namespace Common { -Action::Action(String des, ActionCategory cat, ActionType ty, - int pr, int gr, int fl) { +Action::Action(int32 i, String des, + ActionCategory cat, ActionType typ, + int pri, int grp, int flg) { + id = i; description = des; category = cat; - type = ty; - priority = pr; - group = gr; - flags = fl; + type = typ; + priority = pri; + group = grp; + flags = flg; _hwKey = 0; _parent = 0; } diff --git a/backends/common/action.h b/backends/common/action.h index a9e9356af8..d9ecb873b3 100644 --- a/backends/common/action.h +++ b/backends/common/action.h @@ -49,8 +49,12 @@ enum ActionType { kRightClickAction, kSaveAction, kMenuAction, + kQuitAction, kVirtualKeyboardAction, - kRemapKeysAction, + kKeyRemapAction, + kVolumeUpAction, + kVolumeDownAction, + kActionTypeMax }; @@ -69,9 +73,9 @@ struct Action { int32 id; /** Human readable description */ String description; + /** Events to be sent when mapped key is pressed */ List events; - ActionCategory category; ActionType type; int priority; @@ -84,16 +88,17 @@ private: Keymap *_parent; public: - Action( String des = "", - ActionCategory cat = kGenericActionCategory, - ActionType ty = kGenericActionType, - int pr = 0, int gr = 0, int fl = 0 ); + 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 { diff --git a/backends/common/hardware-key.h b/backends/common/hardware-key.h index 4aba5280bf..1442dbd728 100644 --- a/backends/common/hardware-key.h +++ b/backends/common/hardware-key.h @@ -48,14 +48,15 @@ struct HardwareKey { ActionType preferredType; int16 group; - HardwareKey(KeyState ks = KeyState(), String des = "", - ActionCategory cat = kGenericActionCategory, - ActionType ty = kGenericActionType, int gr = 0) { - key = ks; - description = des; - preferredCategory = cat; - preferredType = ty; - group = gr; + 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; } }; @@ -69,7 +70,7 @@ class HardwareKeySet { public: HardwareKeySet() {} - ~HardwareKeySet() { + virtual ~HardwareKeySet() { List::iterator it; for (it = _keys.begin(); it != _keys.end(); it++) delete *it; @@ -113,9 +114,9 @@ private: List::iterator it; for (it = _keys.begin(); it != _keys.end(); it++) { if ((*it)->id == key->id) - error("HardwareKey with id %d already given!", 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("HardwareKey with same KeyState already given!"); + error("Error adding HardwareKey '%s' - key already in use!", key->description.c_str()); } } diff --git a/backends/common/keymap-manager.cpp b/backends/common/keymap-manager.cpp index 7af74f4edc..81a42507c5 100644 --- a/backends/common/keymap-manager.cpp +++ b/backends/common/keymap-manager.cpp @@ -28,13 +28,14 @@ namespace Common { - -void KeymapManager::Domain::addDefaultKeymap(Keymap *map) { +void KeymapManager::Domain::setDefaultKeymap(Keymap *map) { + delete _defaultKeymap; _defaultKeymap = map; } void KeymapManager::Domain::addKeymap(const String& name, Keymap *map) { - if (_keymaps.contains(name)) + KeymapMap::iterator it = _keymaps.find(name); + if (it != _keymaps.end()) delete _keymaps[name]; _keymaps[name] = map; } @@ -44,6 +45,7 @@ void KeymapManager::Domain::deleteAllKeyMaps() { for (it = _keymaps.begin(); it != _keymaps.end(); it++) delete it->_value; _keymaps.clear(); + delete _defaultKeymap; } Keymap *KeymapManager::Domain::getDefaultKeymap() { @@ -58,6 +60,15 @@ Keymap *KeymapManager::Domain::getKeymap(const String& name) { return 0; } +KeymapManager::KeymapManager() { + _hardwareKeys = 0; +} + +KeymapManager::~KeymapManager() { + delete _hardwareKeys; +} + + void KeymapManager::registerHardwareKeySet(HardwareKeySet *keys) { if (_hardwareKeys) error("Hardware key set already registered!"); @@ -68,7 +79,7 @@ void KeymapManager::registerDefaultGlobalKeymap(Keymap *map) { ConfigManager::Domain *dom = ConfMan.getDomain(ConfigManager::kApplicationDomain); assert(dom); initKeymap(dom, "default", map); - _globalDomain.addDefaultKeymap(map); + _globalDomain.setDefaultKeymap(map); } void KeymapManager::registerGlobalKeymap(const String& name, Keymap *map) { @@ -84,7 +95,7 @@ void KeymapManager::registerDefaultGameKeymap(Keymap *map) { assert(dom); initKeymap(dom, "default", map); - _gameDomain.addDefaultKeymap(map); + _gameDomain.setDefaultKeymap(map); } void KeymapManager::registerGameKeymap(const String& name, Keymap *map) { @@ -99,8 +110,7 @@ void KeymapManager::initKeymap(ConfigManager::Domain *domain, const String& name, Keymap *map) { if (!loadKeymap(domain, name, map)) - return; - automaticMap(map); + automaticMap(map); } bool KeymapManager::loadKeymap(ConfigManager::Domain *domain, @@ -155,10 +165,9 @@ bool KeymapManager::isMapComplete(const Keymap *map) { numberMapped++; } else { allMapped = false; - break; } } - return (allMapped || numberMapped == _hardwareKeys->count()); + return allMapped || (numberMapped == _hardwareKeys->count()); } void KeymapManager::saveKeymap(ConfigManager::Domain *domain, @@ -196,7 +205,7 @@ void KeymapManager::automaticMap(Keymap *map) { if ((*keyIt)->preferredType == act->type) { selectedKey = keyIt; break; - } else if ((*keyIt)->preferredCategory == act->category) { + } else if ((*keyIt)->preferredCategory == act->category && selectedKey == keys.end()) { selectedKey = keyIt; } } diff --git a/backends/common/keymap-manager.h b/backends/common/keymap-manager.h index cc126c3284..a911bc8d61 100644 --- a/backends/common/keymap-manager.h +++ b/backends/common/keymap-manager.h @@ -42,7 +42,7 @@ public: Domain() : _defaultKeymap(0) {} ~Domain() { deleteAllKeyMaps(); } - void addDefaultKeymap(Keymap *map); + void setDefaultKeymap(Keymap *map); void addKeymap(const String& name, Keymap *map); void deleteAllKeyMaps(); @@ -58,6 +58,9 @@ public: KeymapMap _keymaps; }; + KeymapManager(); + ~KeymapManager(); + void registerHardwareKeySet(HardwareKeySet *keys); void registerDefaultGlobalKeymap(Keymap *map); diff --git a/backends/common/keymapper.cpp b/backends/common/keymapper.cpp index b31333aebb..70664b80d9 100644 --- a/backends/common/keymapper.cpp +++ b/backends/common/keymapper.cpp @@ -24,31 +24,50 @@ */ #include "backends/common/keymapper.h" -#include "backends/common/keymap-manager.h" #include "common/config-manager.h" namespace Common { Keymapper::Keymapper(EventManager *evtMgr) { _eventMan = evtMgr; _keymapMan = new KeymapManager(); - _currentMap = 0; +} + +Keymapper::~Keymapper() { + delete _keymapMan; } void Keymapper::registerHardwareKeySet(HardwareKeySet *keys) { _keymapMan->registerHardwareKeySet(keys); } -void Keymapper::addGlobalKeyMap(const String& name, Keymap *keymap) { +void Keymapper::addGlobalKeymap(const String& name, Keymap *keymap) { _keymapMan->registerGlobalKeymap(name, keymap); } -void Keymapper::addGameKeyMap(const String& name, Keymap *keymap) { - if (_gameId.size() == 0) { +void Keymapper::setDefaultGlobalKeymap(Keymap *keymap) { + _keymapMan->registerDefaultGlobalKeymap(keymap); + pushKeymap(keymap, false); +} + +void Keymapper::addGameKeymap(const String& name, Keymap *keymap) { + if (checkGameInit()) + _keymapMan->registerGameKeymap(name, keymap); +} + +void Keymapper::setDefaultGameKeymap(Keymap *keymap) { + if (checkGameInit()) { + _keymapMan->registerDefaultGameKeymap(keymap); + pushKeymap(keymap, true); + } +} + +bool Keymapper::checkGameInit() { + if (_gameId.empty()) { initGame(); - if (_gameId.size() == 0) - return; + if (_gameId.empty()) + return false; } - _keymapMan->registerGameKeymap(name, keymap); + return true; } void Keymapper::initGame() { @@ -65,17 +84,28 @@ void Keymapper::cleanupGame() { _gameId.clear(); } - -bool Keymapper::switchKeymap(const String& name) { - Keymap *new_map = _keymapMan->getKeymap(name); - if (!new_map) { +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; } - _currentMap = new_map; + 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); } @@ -85,9 +115,16 @@ bool Keymapper::mapKeyUp(const KeyState& key) { } bool Keymapper::mapKey(const KeyState& key, bool isKeyDown) { - if (!_currentMap) return false; - Action *action = _currentMap->getMappedAction(key); + 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::iterator it; for (it = action->events.begin(); it != action->events.end(); it++) { Event evt = *it; diff --git a/backends/common/keymapper.h b/backends/common/keymapper.h index a7d5386171..ff9e476739 100644 --- a/backends/common/keymapper.h +++ b/backends/common/keymapper.h @@ -28,19 +28,18 @@ #include "common/events.h" #include "common/list.h" - +#include "common/stack.h" +#include "backends/common/hardware-key.h" +#include "backends/common/keymap.h" +#include "backends/common/keymap-manager.h" namespace Common { -struct HardwareKey; -class HardwareKeySet; -class KeymapManager; -class Keymap; - class Keymapper { public: Keymapper(EventManager *eventMan); + ~Keymapper(); /** * Registers a HardwareKeySet with the Keymapper @@ -48,19 +47,30 @@ public: */ void registerHardwareKeySet(HardwareKeySet *keys); + /** - * Add a keymap to the global domain. + * 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); + void addGlobalKeymap(const String& name, Keymap *keymap); /** - * Add a keymap to the game domain. + * 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); + void addGameKeymap(const String& name, Keymap *keymap); + + /** + * Sets the default keymap for the game domain. + */ + void setDefaultGameKeymap(Keymap *keymap); /** * Initialise the keymapper for a new game @@ -73,19 +83,25 @@ public: void cleanupGame(); /** - * Switch the active keymap. - * @param name name of the new 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 switchKeymap(const String& name); + 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 + * @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); @@ -103,6 +119,9 @@ public: private: + void pushKeymap(Keymap *newMap, bool inherit); + bool checkGameInit(); + typedef List::iterator Iterator; EventManager *_eventMan; @@ -110,7 +129,12 @@ private: String _gameId; - Keymap *_currentMap; + struct MapRecord { + Keymap* keymap; + bool inherit; + }; + + Stack _activeMaps; }; diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp index fa9ff38330..9bafdd9e4f 100644 --- a/backends/events/default/default-events.cpp +++ b/backends/events/default/default-events.cpp @@ -196,10 +196,11 @@ DefaultEventManager::DefaultEventManager(OSystem *boss) : } _vk = new Common::VirtualKeyboard(); - _keyMapper = new Common::Keymapper(this); + _keymapper = new Common::Keymapper(this); } DefaultEventManager::~DefaultEventManager() { + delete _keymapper; delete _vk; _boss->lockMutex(_timeMutex); _boss->lockMutex(_recorderMutex); @@ -372,10 +373,10 @@ bool DefaultEventManager::pollEvent(Common::Event &event) { if (result) { // send key press events to keymapper if (event.type == Common::EVENT_KEYDOWN) { - if (_keyMapper->mapKeyDown(event.kbd)) + if (_keymapper->mapKeyDown(event.kbd)) result = false; } else if (event.type == Common::EVENT_KEYUP) { - if (_keyMapper->mapKeyUp(event.kbd)) + if (_keymapper->mapKeyUp(event.kbd)) result = false; } } diff --git a/backends/events/default/default-events.h b/backends/events/default/default-events.h index 2dd3ccc6e2..8e24120ad0 100644 --- a/backends/events/default/default-events.h +++ b/backends/events/default/default-events.h @@ -32,7 +32,6 @@ namespace Common { class VirtualKeyboard; - class Keymapper; } /* @@ -51,7 +50,7 @@ class DefaultEventManager : public Common::EventManager { OSystem *_boss; Common::VirtualKeyboard *_vk; - Common::Keymapper *_keyMapper; + Common::Keymapper *_keymapper; Common::Queue _artificialEventQueue; int _artificialEventCounter; @@ -130,6 +129,7 @@ public: virtual int getButtonState() const { return _buttonState; } virtual int getModifierState() const { return _modifierState; } virtual int shouldQuit() const { return _shouldQuit; } + virtual Common::Keymapper *getKeymapper() { return _keymapper; } }; #endif diff --git a/backends/platform/sdl/events.cpp b/backends/platform/sdl/events.cpp index a4a72ca380..830555e514 100644 --- a/backends/platform/sdl/events.cpp +++ b/backends/platform/sdl/events.cpp @@ -24,6 +24,7 @@ */ #include "backends/platform/sdl/sdl.h" +#include "backends/common/keymapper.h" #include "common/util.h" #include "common/events.h" @@ -520,3 +521,36 @@ bool OSystem_SDL::remapKey(SDL_Event &ev, Common::Event &event) { return false; } +void OSystem_SDL::setupKeymapper() { + using namespace Common; + Keymapper *mapper = getEventManager()->getKeymapper(); + + HardwareKeySet *keySet = new HardwareKeySet(); + keySet->addHardwareKey(new HardwareKey( 'a', KeyState(KEYCODE_a), "a" )); + keySet->addHardwareKey(new HardwareKey( 's', KeyState(KEYCODE_s), "s" )); + keySet->addHardwareKey(new HardwareKey( 'd', KeyState(KEYCODE_d), "d" )); + keySet->addHardwareKey(new HardwareKey( 'f', KeyState(KEYCODE_f), "f" )); + mapper->registerHardwareKeySet(keySet); + + Keymap *global = new Keymap(); + Action *act; + Event evt; + + #define ADD_KEYDOWN_EVENT(kc, asc, flags) \ + evt.type = EVENT_KEYDOWN; \ + evt.kbd = KeyState(kc, asc, flags); \ + act->events.push_back(evt); + + act = new Action('MENU', "Menu", kGenericActionCategory, kMenuAction); + ADD_KEYDOWN_EVENT(KEYCODE_F5, ASCII_F5, 0) + global->addAction(act); + + act = new Action('QUIT', "Quit", kGenericActionCategory, kQuitAction); + ADD_KEYDOWN_EVENT(KEYCODE_ESCAPE, ASCII_ESCAPE, 0); + global->addAction(act); + + #undef ADD_KEYDOWN_EVENT + + mapper->setDefaultGlobalKeymap(global); +} + diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp index d8394b5c9c..14668dac11 100644 --- a/backends/platform/sdl/sdl.cpp +++ b/backends/platform/sdl/sdl.cpp @@ -148,6 +148,9 @@ void OSystem_SDL::initBackend() { _timerID = SDL_AddTimer(10, &timer_handler, _timer); } + // Provide the keymapper with backend's set of keys + setupKeymapper(); + // Invoke parent implementation of this method OSystem::initBackend(); diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h index 4ad588f5f5..3fbfa8ba0d 100644 --- a/backends/platform/sdl/sdl.h +++ b/backends/platform/sdl/sdl.h @@ -142,6 +142,9 @@ public: // Returns true if an event was retrieved. virtual bool pollEvent(Common::Event &event); // overloaded by CE backend + // Sets up the keymapper with the backends hardware key set + virtual void setupKeymapper(); + // Set function that generates samples virtual void setupMixer(); static void mixCallback(void *s, byte *samples, int len); -- cgit v1.2.3