aboutsummaryrefslogtreecommitdiff
path: root/backends
diff options
context:
space:
mode:
authorTarek Soliman2012-02-22 18:30:47 -0600
committerTarek Soliman2012-03-02 20:48:50 -0600
commitd12f21b31db2985faeb2e2a6b9b09cd210f82c34 (patch)
tree7340a06802eded01eb68c224a3e958bb37185a31 /backends
parent4ee1a3aceae7d68c89513f7d122606acbceb1e7c (diff)
downloadscummvm-rg350-d12f21b31db2985faeb2e2a6b9b09cd210f82c34.tar.gz
scummvm-rg350-d12f21b31db2985faeb2e2a6b9b09cd210f82c34.tar.bz2
scummvm-rg350-d12f21b31db2985faeb2e2a6b9b09cd210f82c34.zip
KEYMAPPER: Map non-key custom input events
This also makes the keymapper be in charge of keymapping logic
Diffstat (limited to 'backends')
-rw-r--r--backends/keymapper/keymap.cpp43
-rw-r--r--backends/keymapper/keymap.h12
-rw-r--r--backends/keymapper/keymapper.cpp149
-rw-r--r--backends/keymapper/keymapper.h31
-rw-r--r--backends/keymapper/remap-dialog.cpp54
-rw-r--r--backends/keymapper/remap-dialog.h4
6 files changed, 208 insertions, 85 deletions
diff --git a/backends/keymapper/keymap.cpp b/backends/keymapper/keymap.cpp
index f5155ce1b5..e95dd6afb5 100644
--- a/backends/keymapper/keymap.cpp
+++ b/backends/keymapper/keymap.cpp
@@ -33,15 +33,17 @@
namespace Common {
-Keymap::Keymap(const Keymap& km) : _actions(km._actions), _keymap(), _configDomain(0) {
+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 HardwareInput *hwInput = (*it)->getMappedInput();
- //FIXME: Add support for kHardwareInputTypeGeneric
- if (hwInput && hwInput->type == kHardwareInputTypeKeyboard) {
- _keymap[hwInput->key] = *it;
+ if (hwInput) {
+ if (hwInput->type == kHardwareInputTypeKeyboard)
+ _keymap[hwInput->key] = *it;
+ else if (hwInput->type == kHardwareInputTypeGeneric)
+ _nonkeymap[hwInput->inputCode] = *it;
}
}
}
@@ -61,17 +63,20 @@ void Keymap::addAction(Action *action) {
}
void Keymap::registerMapping(Action *action, const HardwareInput *hwInput) {
- HashMap<KeyState, Action *>::iterator it;
-
- //FIXME: Add support for kHardwareInputTypeGeneric
if (hwInput->type == kHardwareInputTypeKeyboard) {
- it = _keymap.find(hwInput->key);
-
- // if key is already mapped to a different action then un-map it
- if (it != _keymap.end() && action != it->_value) {
+ 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;
}
}
@@ -79,9 +84,10 @@ void Keymap::unregisterMapping(Action *action) {
const HardwareInput *hwInput = action->getMappedInput();
if (hwInput) {
- //FIXME: Add support for kHardwareInputTypeGeneric
if (hwInput->type == kHardwareInputTypeKeyboard)
_keymap.erase(hwInput->key);
+ else if (hwInput->type == kHardwareInputTypeGeneric)
+ _nonkeymap.erase(hwInput->inputCode);
}
}
@@ -121,6 +127,17 @@ 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;
}
diff --git a/backends/keymapper/keymap.h b/backends/keymapper/keymap.h
index 4c3e89700f..6eaec7dcaf 100644
--- a/backends/keymapper/keymap.h
+++ b/backends/keymapper/keymap.h
@@ -33,12 +33,10 @@
#include "common/keyboard.h"
#include "common/list.h"
#include "backends/keymapper/action.h"
+#include "backends/keymapper/hardware-input.h"
namespace Common {
-struct HardwareInput;
-class HardwareInputSet;
-
/**
* Hash function for KeyState
*/
@@ -76,6 +74,13 @@ public:
*/
Action *getMappedAction(const KeyState& ks) const;
+ /**
+ * Find the Action that a generic input is mapped to
+ * @param code the input code that is mapped to the required Action
+ * @return a pointer to the Action or 0 if no
+ */
+ Action *getMappedAction(const HardwareInputCode code) const;
+
void setConfigDomain(ConfigManager::Domain *dom);
/**
@@ -130,6 +135,7 @@ private:
String _name;
List<Action *> _actions;
HashMap<KeyState, Action *> _keymap;
+ HashMap<HardwareInputCode, Action *> _nonkeymap;
ConfigManager::Domain *_configDomain;
};
diff --git a/backends/keymapper/keymapper.cpp b/backends/keymapper/keymapper.cpp
index 4742886207..99bcb44179 100644
--- a/backends/keymapper/keymapper.cpp
+++ b/backends/keymapper/keymapper.cpp
@@ -54,7 +54,7 @@ Keymap *Keymapper::Domain::getKeymap(const String& name) {
}
Keymapper::Keymapper(EventManager *evtMgr)
- : _eventMan(evtMgr), _enabled(true), _hardwareInputs(0) {
+ : _eventMan(evtMgr), _enabled(true), _remapping(false), _hardwareInputs(0), _actionToRemap(0) {
ConfigManager::Domain *confDom = ConfMan.getDomain(ConfigManager::kKeymapperDomain);
_globalDomain.setConfigDomain(confDom);
@@ -183,13 +183,16 @@ List<Event> Keymapper::mapEvent(const Event &ev, EventSource *source) {
if (source && !source->allowMapping()) {
return DefaultEventMapper::mapEvent(ev, source);
}
-
List<Event> mappedEvents;
- if (ev.type == Common::EVENT_KEYDOWN)
+ if (_remapping)
+ mappedEvents = remap(ev);
+ else if (ev.type == Common::EVENT_KEYDOWN)
mappedEvents = mapKeyDown(ev.kbd);
else if (ev.type == Common::EVENT_KEYUP)
mappedEvents = mapKeyUp(ev.kbd);
+ else if (ev.type == Common::EVENT_CUSTOM_BACKEND_HARDWARE)
+ mappedEvents = mapNonKey(ev.customType);
if (!mappedEvents.empty())
return mappedEvents;
@@ -197,6 +200,13 @@ List<Event> Keymapper::mapEvent(const Event &ev, EventSource *source) {
return DefaultEventMapper::mapEvent(ev, source);
}
+void Keymapper::startRemappingMode(Action *actionToRemap) {
+ assert(!_remapping);
+
+ _remapping = true;
+ _actionToRemap = actionToRemap;
+}
+
List<Event> Keymapper::mapKeyDown(const KeyState& key) {
return mapKey(key, true);
}
@@ -236,7 +246,30 @@ List<Event> Keymapper::mapKey(const KeyState& key, bool keyDown) {
if (!action)
return List<Event>();
- return executeAction(action, keyDown);
+ return executeAction(action, keyDown ? kIncomingKeyDown : kIncomingKeyUp);
+}
+
+
+List<Event> Keymapper::mapNonKey(const HardwareInputCode code) {
+ if (!_enabled || _activeMaps.empty())
+ return List<Event>();
+
+ Action *action = 0;
+
+ // Search for nonkey in active keymap stack
+ for (int i = _activeMaps.size() - 1; i >= 0; --i) {
+ MapRecord mr = _activeMaps[i];
+ debug(5, "Keymapper::mapKey keymap: %s", mr.keymap->getName().c_str());
+ action = mr.keymap->getMappedAction(code);
+
+ if (action || !mr.transparent)
+ break;
+ }
+
+ if (!action)
+ return List<Event>();
+
+ return executeAction(action);
}
Action *Keymapper::getAction(const KeyState& key) {
@@ -245,52 +278,57 @@ Action *Keymapper::getAction(const KeyState& key) {
return action;
}
-List<Event> Keymapper::executeAction(const Action *action, bool keyDown) {
+List<Event> Keymapper::executeAction(const Action *action, IncomingEventType incomingType) {
List<Event> mappedEvents;
List<Event>::const_iterator it;
for (it = action->events.begin(); it != action->events.end(); ++it) {
- Event evt = *it;
-
- switch (evt.type) {
- case EVENT_KEYDOWN:
- if (!keyDown) evt.type = EVENT_KEYUP;
- break;
- case EVENT_KEYUP:
- if (keyDown) evt.type = EVENT_KEYDOWN;
- break;
- case EVENT_LBUTTONDOWN:
- if (!keyDown) evt.type = EVENT_LBUTTONUP;
- break;
- case EVENT_LBUTTONUP:
- if (keyDown) evt.type = EVENT_LBUTTONDOWN;
- break;
- case EVENT_RBUTTONDOWN:
- if (!keyDown) evt.type = EVENT_RBUTTONUP;
- break;
- case EVENT_RBUTTONUP:
- if (keyDown) evt.type = EVENT_RBUTTONDOWN;
- break;
- case EVENT_MBUTTONDOWN:
- if (!keyDown) evt.type = EVENT_MBUTTONUP;
- break;
- case EVENT_MBUTTONUP:
- if (keyDown) evt.type = EVENT_MBUTTONDOWN;
- break;
- case EVENT_MAINMENU:
- if (!keyDown) evt.type = EVENT_MAINMENU;
- break;
- default:
- // don't deliver other events on key up
- if (!keyDown) continue;
+ Event evt = Event(*it);
+ EventType convertedType = convertDownToUp(evt.type);
+
+ // hardware keys need to send up instead when they are up
+ if (incomingType == kIncomingKeyUp) {
+ if (convertedType == EVENT_INVALID)
+ continue; // don't send any non-down-converted events on up they were already sent on down
+ evt.type = convertedType;
}
evt.mouse = _eventMan->getMousePos();
mappedEvents.push_back(evt);
+
+ // non-keys need to send up as well
+ // TODO: implement a way to add a delay
+ if (incomingType == kIncomingNonKey) {
+ if (convertedType == EVENT_INVALID)
+ continue; // don't send any non-down-converted events on up they were already sent on down
+ evt.type = convertedType;
+ mappedEvents.push_back(evt);
+ }
}
return mappedEvents;
}
+EventType Keymapper::convertDownToUp(EventType type) {
+ EventType result = EVENT_INVALID;
+ switch (type) {
+ case EVENT_KEYDOWN:
+ result = EVENT_KEYUP;
+ break;
+ case EVENT_LBUTTONDOWN:
+ result = EVENT_LBUTTONUP;
+ break;
+ case EVENT_RBUTTONDOWN:
+ result = EVENT_RBUTTONUP;
+ break;
+ case EVENT_MBUTTONDOWN:
+ result = EVENT_MBUTTONUP;
+ break;
+ default:
+ break;
+ }
+ return result;
+}
+
const HardwareInput *Keymapper::findHardwareInput(const KeyState& key) {
return (_hardwareInputs) ? _hardwareInputs->findHardwareInput(key) : 0;
}
@@ -299,6 +337,41 @@ const HardwareInput *Keymapper::findHardwareInput(const HardwareInputCode code)
return (_hardwareInputs) ? _hardwareInputs->findHardwareInput(code) : 0;
}
+List<Event> Keymapper::remap(const Event &ev) {
+ assert(_remapping);
+ assert(_actionToRemap);
+
+ List<Event> list;
+
+ const HardwareInput *hwInput = 0;
+ Event mappedEvent;
+
+ switch (ev.type) {
+ case EVENT_KEYDOWN:
+ // eat the event by returning an event invalid
+ mappedEvent.type = EVENT_INVALID;
+ list.push_back(mappedEvent);
+ break;
+ case EVENT_KEYUP:
+ hwInput = findHardwareInput(ev.kbd);
+ break;
+ case EVENT_CUSTOM_BACKEND_HARDWARE:
+ hwInput = findHardwareInput(ev.customType);
+ break;
+ default:
+ break;
+ }
+ if (hwInput) {
+ _actionToRemap->mapInput(hwInput);
+ _actionToRemap->getParent()->saveMappings();
+ _remapping = false;
+ _actionToRemap = 0;
+ mappedEvent.type = EVENT_GUI_REMAP_COMPLETE_ACTION;
+ list.push_back(mappedEvent);
+ }
+ return list;
+}
+
} // End of namespace Common
#endif // #ifdef ENABLE_KEYMAPPER
diff --git a/backends/keymapper/keymapper.h b/backends/keymapper/keymapper.h
index 9a80911dbf..1e8d1c08c3 100644
--- a/backends/keymapper/keymapper.h
+++ b/backends/keymapper/keymapper.h
@@ -149,6 +149,7 @@ public:
* @return mapped events
*/
List<Event> mapKey(const KeyState& key, bool keyDown);
+ List<Event> mapNonKey(const HardwareInputCode code);
/**
* @brief Map a key down event.
@@ -168,6 +169,24 @@ public:
void setEnabled(bool enabled) { _enabled = enabled; }
/**
+ * @brief Activate remapping mode
+ * While this mode is active, any mappable event will be bound to the action
+ * provided.
+ * @param actionToRemap Action that is the target of the remap
+ */
+ void startRemappingMode(Action *actionToRemap);
+
+ /**
+ * @brief Force-stop the remapping mode
+ */
+ void stopRemappingMode() { _remapping = false; }
+
+ /**
+ * Query whether the keymapper is currently in the remapping mode
+ */
+ bool isRemapping() const { return _remapping; }
+
+ /**
* Return a HardwareInput pointer for the given key state
*/
const HardwareInput *findHardwareInput(const KeyState& key);
@@ -183,6 +202,12 @@ public:
private:
+ enum IncomingEventType {
+ kIncomingKeyDown,
+ kIncomingKeyUp,
+ kIncomingNonKey
+ };
+
void initKeymap(Domain &domain, Keymap *keymap);
Domain _globalDomain;
@@ -193,12 +218,16 @@ private:
void pushKeymap(Keymap *newMap, bool transparent, bool global);
Action *getAction(const KeyState& key);
- List<Event> executeAction(const Action *act, bool keyDown);
+ List<Event> executeAction(const Action *act, IncomingEventType incomingType = kIncomingNonKey);
+ EventType convertDownToUp(EventType eventType);
+ List<Event> remap(const Event &ev);
EventManager *_eventMan;
bool _enabled;
+ bool _remapping;
+ Action *_actionToRemap;
Stack<MapRecord> _activeMaps;
HashMap<KeyState, Action *> _keysDown;
diff --git a/backends/keymapper/remap-dialog.cpp b/backends/keymapper/remap-dialog.cpp
index 29f0174aad..009c2201a9 100644
--- a/backends/keymapper/remap-dialog.cpp
+++ b/backends/keymapper/remap-dialog.cpp
@@ -39,7 +39,7 @@ enum {
};
RemapDialog::RemapDialog()
- : Dialog("KeyMapper"), _keymapTable(0), _activeRemapAction(0), _topAction(0), _remapTimeout(0), _topKeymapIsGui(false) {
+ : Dialog("KeyMapper"), _keymapTable(0), _topAction(0), _remapTimeout(0), _topKeymapIsGui(false) {
_keymapper = g_system->getEventManager()->getKeymapper();
assert(_keymapper);
@@ -243,16 +243,14 @@ void RemapDialog::clearMapping(uint i) {
return;
debug(3, "clear the mapping %u", i);
- _activeRemapAction = _currentActions[_topAction + i].action;
- _activeRemapAction->mapInput(0);
- _activeRemapAction->getParent()->saveMappings();
+ Action *activeRemapAction = _currentActions[_topAction + i].action;
+ activeRemapAction->mapInput(0);
+ activeRemapAction->getParent()->saveMappings();
_changes = true;
// force refresh
- _topAction = -1;
+ stopRemapping(true);
refreshKeymap();
-
- _activeRemapAction = 0;
}
void RemapDialog::startRemapping(uint i) {
@@ -260,57 +258,56 @@ void RemapDialog::startRemapping(uint i) {
return;
_remapTimeout = g_system->getMillis() + kRemapTimeoutDelay;
- _activeRemapAction = _currentActions[_topAction + i].action;
+ Action *activeRemapAction = _currentActions[_topAction + i].action;
_keymapWidgets[i].keyButton->setLabel("...");
_keymapWidgets[i].keyButton->draw();
- _keymapper->setEnabled(false);
+ _keymapper->startRemappingMode(activeRemapAction);
}
-void RemapDialog::stopRemapping() {
+void RemapDialog::stopRemapping(bool force) {
_topAction = -1;
refreshKeymap();
- _activeRemapAction = 0;
-
- _keymapper->setEnabled(true);
+ if (force)
+ _keymapper->stopRemappingMode();
}
void RemapDialog::handleKeyDown(Common::KeyState state) {
- if (_activeRemapAction)
+ if (_keymapper->isRemapping())
return;
GUI::Dialog::handleKeyDown(state);
}
void RemapDialog::handleKeyUp(Common::KeyState state) {
- if (_activeRemapAction) {
- const HardwareInput *hwInput = _keymapper->findHardwareInput(state);
+ if (_keymapper->isRemapping())
+ return;
- debug(4, "RemapDialog::handleKeyUp Key: %d, %d (%c), %x", state.keycode, state.ascii, (state.ascii ? state.ascii : ' '), state.flags);
+ GUI::Dialog::handleKeyUp(state);
+}
- if (hwInput) {
- _activeRemapAction->mapInput(hwInput);
- _activeRemapAction->getParent()->saveMappings();
- _changes = true;
- stopRemapping();
- }
+void RemapDialog::handleOtherEvent(Event ev) {
+ if (ev.type == EVENT_GUI_REMAP_COMPLETE_ACTION) {
+ // _keymapper is telling us that something changed
+ _changes = true;
+ stopRemapping();
} else {
- GUI::Dialog::handleKeyUp(state);
+ GUI::Dialog::handleOtherEvent(ev);
}
}
void RemapDialog::handleMouseDown(int x, int y, int button, int clickCount) {
- if (_activeRemapAction)
+ if (_keymapper->isRemapping())
stopRemapping();
else
Dialog::handleMouseDown(x, y, button, clickCount);
}
void RemapDialog::handleTickle() {
- if (_activeRemapAction && g_system->getMillis() > _remapTimeout)
- stopRemapping();
+ if (_keymapper->isRemapping() && g_system->getMillis() > _remapTimeout)
+ stopRemapping(true);
Dialog::handleTickle();
}
@@ -358,9 +355,10 @@ void RemapDialog::loadKeymap() {
while (inputIt != freeInputs.end()) {
Action *act = 0;
- // FIXME: Add support for kHardwareInputTypeGeneric
if (input->type == kHardwareInputTypeKeyboard)
act = mr.keymap->getMappedAction(input->key);
+ else if (input->type == kHardwareInputTypeGeneric)
+ act = mr.keymap->getMappedAction(input->inputCode);
if (act) {
ActionInfo info = {act, true, act->description + " (" + mr.keymap->getName() + ")"};
diff --git a/backends/keymapper/remap-dialog.h b/backends/keymapper/remap-dialog.h
index 143deca4cf..82c68405db 100644
--- a/backends/keymapper/remap-dialog.h
+++ b/backends/keymapper/remap-dialog.h
@@ -50,6 +50,7 @@ public:
virtual void handleKeyUp(Common::KeyState state);
virtual void handleMouseDown(int x, int y, int button, int clickCount);
virtual void handleTickle();
+ virtual void handleOtherEvent(Common::Event ev);
protected:
struct ActionWidgets {
@@ -67,7 +68,7 @@ protected:
void refreshKeymap();
void clearMapping(uint i);
void startRemapping(uint i);
- void stopRemapping();
+ void stopRemapping(bool force = false);
Keymapper *_keymapper;
Keymap** _keymapTable;
@@ -85,7 +86,6 @@ protected:
uint _rowCount;
Array<ActionWidgets> _keymapWidgets;
- Action *_activeRemapAction;
uint32 _remapTimeout;
static const uint32 kRemapTimeoutDelay = 3000;