Speech bubbles can point down right.
[scummvm-innocent.git] / backends / keymapper / keymapper.cpp
blobc0c454168cd99be93aa18bafea664a1bcf7b6c7b
1 /* ScummVM - Graphic Adventure Engine
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 * $URL$
22 * $Id$
26 #include "backends/keymapper/keymapper.h"
28 #ifdef ENABLE_KEYMAPPER
30 #include "common/config-manager.h"
32 namespace Common {
34 void Keymapper::Domain::addKeymap(Keymap *map) {
35 iterator it = find(map->getName());
37 if (it != end())
38 delete it->_value;
40 setVal(map->getName(), map);
43 void Keymapper::Domain::deleteAllKeyMaps() {
44 for (iterator it = begin(); it != end(); it++)
45 delete it->_value;
47 clear();
50 Keymap *Keymapper::Domain::getKeymap(const String& name) {
51 iterator it = find(name);
53 if (it != end())
54 return it->_value;
55 else
56 return 0;
59 Keymapper::Keymapper(EventManager *evtMgr)
60 : _eventMan(evtMgr), _enabled(true), _hardwareKeys(0) {
61 ConfigManager::Domain *confDom = ConfMan.getDomain(ConfigManager::kKeymapperDomain);
63 _globalDomain.setConfigDomain(confDom);
66 Keymapper::~Keymapper() {
67 delete _hardwareKeys;
70 void Keymapper::registerHardwareKeySet(HardwareKeySet *keys) {
71 if (_hardwareKeys)
72 error("Hardware key set already registered");
74 if (!keys) {
75 warning("No hardware keys are supplied");
76 return;
79 _hardwareKeys = keys;
82 void Keymapper::addGlobalKeymap(Keymap *keymap) {
83 initKeymap(_globalDomain, keymap);
86 void Keymapper::addGameKeymap(Keymap *keymap) {
87 if (ConfMan.getActiveDomain() == 0)
88 error("Call to Keymapper::addGameKeymap when no game loaded");
90 // Detect whether the active game changed since last call.
91 // If so, flush the game key configuration.
92 if (_gameDomain.getConfigDomain() != ConfMan.getActiveDomain()) {
93 cleanupGameKeymaps();
94 _gameDomain.setConfigDomain(ConfMan.getActiveDomain());
97 initKeymap(_gameDomain, keymap);
100 void Keymapper::initKeymap(Domain &domain, Keymap *map) {
101 if (!_hardwareKeys) {
102 warning("No hardware keys were registered yet (%s)", map->getName().c_str());
103 return;
106 map->setConfigDomain(domain.getConfigDomain());
107 map->loadMappings(_hardwareKeys);
109 if (map->isComplete(_hardwareKeys) == false) {
110 map->automaticMapping(_hardwareKeys);
111 map->saveMappings();
112 ConfMan.flushToDisk();
115 domain.addKeymap(map);
118 void Keymapper::cleanupGameKeymaps() {
119 // Flush all game specific keymaps
120 _gameDomain.deleteAllKeyMaps();
122 // Now restore the stack of active maps. Re-add all global keymaps, drop
123 // the game specific (=deleted) ones.
124 Stack<MapRecord> newStack;
126 for (int i = 0; i < _activeMaps.size(); i++) {
127 if (_activeMaps[i].global)
128 newStack.push(_activeMaps[i]);
131 _activeMaps = newStack;
134 Keymap *Keymapper::getKeymap(const String& name, bool &global) {
135 Keymap *keymap = _gameDomain.getKeymap(name);
136 global = false;
138 if (!keymap) {
139 keymap = _globalDomain.getKeymap(name);
140 global = true;
143 return keymap;
146 bool Keymapper::pushKeymap(const String& name, bool inherit) {
147 bool global;
148 Keymap *newMap = getKeymap(name, global);
150 if (!newMap) {
151 warning("Keymap '%s' not registered", name.c_str());
152 return false;
155 pushKeymap(newMap, inherit, global);
157 return true;
160 void Keymapper::pushKeymap(Keymap *newMap, bool inherit, bool global) {
161 MapRecord mr = {newMap, inherit, global};
163 _activeMaps.push(mr);
166 void Keymapper::popKeymap() {
167 if (!_activeMaps.empty())
168 _activeMaps.pop();
171 bool Keymapper::notifyEvent(const Common::Event &ev) {
172 if (ev.type == Common::EVENT_KEYDOWN)
173 return mapKeyDown(ev.kbd);
174 else if (ev.type == Common::EVENT_KEYUP)
175 return mapKeyUp(ev.kbd);
176 else
177 return false;
180 bool Keymapper::mapKeyDown(const KeyState& key) {
181 return mapKey(key, true);
184 bool Keymapper::mapKeyUp(const KeyState& key) {
185 return mapKey(key, false);
188 bool Keymapper::mapKey(const KeyState& key, bool keyDown) {
189 if (!_enabled || _activeMaps.empty())
190 return false;
192 Action *action = 0;
194 if (keyDown) {
195 // Search for key in active keymap stack
196 for (int i = _activeMaps.size() - 1; i >= 0; --i) {
197 MapRecord mr = _activeMaps[i];
199 action = mr.keymap->getMappedAction(key);
201 if (action || mr.inherit == false)
202 break;
205 if (action)
206 _keysDown[key] = action;
207 } else {
208 HashMap<KeyState, Action*>::iterator it = _keysDown.find(key);
210 if (it != _keysDown.end()) {
211 action = it->_value;
212 _keysDown.erase(key);
216 if (!action)
217 return false;
219 executeAction(action, keyDown);
221 return true;
224 Action *Keymapper::getAction(const KeyState& key) {
225 Action *action = 0;
227 return action;
230 void Keymapper::executeAction(const Action *action, bool keyDown) {
231 List<Event>::const_iterator it;
233 for (it = action->events.begin(); it != action->events.end(); ++it) {
234 Event evt = *it;
236 switch (evt.type) {
237 case EVENT_KEYDOWN:
238 if (!keyDown) evt.type = EVENT_KEYUP;
239 break;
240 case EVENT_KEYUP:
241 if (keyDown) evt.type = EVENT_KEYDOWN;
242 break;
243 case EVENT_LBUTTONDOWN:
244 if (!keyDown) evt.type = EVENT_LBUTTONUP;
245 break;
246 case EVENT_LBUTTONUP:
247 if (keyDown) evt.type = EVENT_LBUTTONDOWN;
248 break;
249 case EVENT_RBUTTONDOWN:
250 if (!keyDown) evt.type = EVENT_RBUTTONUP;
251 break;
252 case EVENT_RBUTTONUP:
253 if (keyDown) evt.type = EVENT_RBUTTONDOWN;
254 break;
255 case EVENT_MBUTTONDOWN:
256 if (!keyDown) evt.type = EVENT_MBUTTONUP;
257 break;
258 case EVENT_MBUTTONUP:
259 if (keyDown) evt.type = EVENT_MBUTTONDOWN;
260 break;
261 default:
262 // don't deliver other events on key up
263 if (!keyDown) continue;
266 evt.mouse = _eventMan->getMousePos();
267 addEvent(evt);
271 const HardwareKey *Keymapper::findHardwareKey(const KeyState& key) {
272 return (_hardwareKeys) ? _hardwareKeys->findHardwareKey(key) : 0;
275 } // end of namespace Common
277 #endif // #ifdef ENABLE_KEYMAPPER