diff options
-rw-r--r-- | backends/keymapper/hardware-input.cpp | 36 | ||||
-rw-r--r-- | backends/keymapper/hardware-input.h | 53 | ||||
-rw-r--r-- | backends/keymapper/keymap.cpp | 46 | ||||
-rw-r--r-- | backends/keymapper/keymap.h | 12 | ||||
-rw-r--r-- | backends/keymapper/keymapper.cpp | 170 | ||||
-rw-r--r-- | backends/keymapper/keymapper.h | 36 | ||||
-rw-r--r-- | backends/keymapper/remap-dialog.cpp | 58 | ||||
-rw-r--r-- | backends/keymapper/remap-dialog.h | 4 | ||||
-rw-r--r-- | common/EventDispatcher.cpp | 6 | ||||
-rw-r--r-- | common/EventMapper.cpp | 38 | ||||
-rw-r--r-- | common/events.h | 17 | ||||
-rw-r--r-- | gui/dialog.cpp | 7 | ||||
-rw-r--r-- | gui/dialog.h | 9 | ||||
-rw-r--r-- | gui/gui-manager.cpp | 3 |
14 files changed, 390 insertions, 105 deletions
diff --git a/backends/keymapper/hardware-input.cpp b/backends/keymapper/hardware-input.cpp index a09f0b54fc..d1f8822ac0 100644 --- a/backends/keymapper/hardware-input.cpp +++ b/backends/keymapper/hardware-input.cpp @@ -209,16 +209,33 @@ const HardwareInput *HardwareInputSet::findHardwareInput(String id) const { return 0; } +const HardwareInput *HardwareInputSet::findHardwareInput(const HardwareInputCode code) const { + List<const HardwareInput *>::const_iterator it; + + for (it = _inputs.begin(); it != _inputs.end(); ++it) { + const HardwareInput *entry = *it; + if (entry->type == kHardwareInputTypeGeneric && entry->inputCode == code) + return entry; + } + return 0; +} + const HardwareInput *HardwareInputSet::findHardwareInput(const KeyState& keystate) const { List<const HardwareInput *>::const_iterator it; for (it = _inputs.begin(); it != _inputs.end(); ++it) { - if ((*it)->key == keystate) - return (*it); + const HardwareInput *entry = *it; + if (entry->type == kHardwareInputTypeKeyboard && entry->key == keystate) + return entry; } return 0; } +void HardwareInputSet::addHardwareInputs(const HardwareInputTableEntry inputs[]) { + for (const HardwareInputTableEntry *entry = inputs; entry->hwId; ++entry) + addHardwareInput(new HardwareInput(entry->hwId, entry->code, entry->desc)); +} + void HardwareInputSet::addHardwareInputs(const KeyTableEntry keys[], const ModifierTableEntry modifiers[]) { const KeyTableEntry *key; const ModifierTableEntry *mod; @@ -247,10 +264,6 @@ void HardwareInputSet::addHardwareInputs(const KeyTableEntry keys[], const Modif } } -void HardwareInputSet::addHardwareInputs(const KeyTableEntry keys[]) { - addHardwareInputs(keys, defaultModifiers); -} - void HardwareInputSet::removeHardwareInput(const HardwareInput *input) { if (!input) return; @@ -259,7 +272,16 @@ void HardwareInputSet::removeHardwareInput(const HardwareInput *input) { for (it = _inputs.begin(); it != _inputs.end(); ++it) { const HardwareInput *entry = (*it); - if (entry->id == input->id || entry->key == input->key) { + bool match = false; + if (entry->id == input->id) + match = true; + else if (input->type == entry->type) { + if (input->type == kHardwareInputTypeGeneric && input->inputCode == entry->inputCode) + match = true; + else if (input->type == kHardwareInputTypeKeyboard && input->key == entry->key) + match = true; + } + if (match) { debug(7, "Removing hardware input [%s] (%s) because it matches [%s] (%s)", entry->id.c_str(), entry->description.c_str(), input->id.c_str(), input->description.c_str()); delete entry; _inputs.erase(it); diff --git a/backends/keymapper/hardware-input.h b/backends/keymapper/hardware-input.h index 9396765bbe..51d4accb5b 100644 --- a/backends/keymapper/hardware-input.h +++ b/backends/keymapper/hardware-input.h @@ -34,6 +34,15 @@ namespace Common { +typedef uint32 HardwareInputCode; + +enum HardwareInputType { + /** Input that sends single events */ + kHardwareInputTypeGeneric, + /** Input that usually send -up and -down events */ + kHardwareInputTypeKeyboard +}; + /** * Describes an available hardware input */ @@ -44,14 +53,33 @@ struct HardwareInput { /** Human readable description */ String description; + const HardwareInputType type; + /** - * The KeyState that is generated by the back-end - * when this hardware key is pressed. - */ + * A platform specific unique identifier for an input event + * generated when this input is triggered. + * This is only relevant when type == kHardwareInputTypeGeneric + */ + HardwareInputCode inputCode; + + /** + * The KeyState that is generated by the back-end + * when this hardware key is pressed. + * This is only relevant when type == kHardwareInputTypeKeyboard + */ KeyState key; - HardwareInput(String i, KeyState ky = KeyState(), String desc = "") - : id(i), key(ky), description(desc) { } + HardwareInput(String i, HardwareInputCode ic = 0, String desc = "") + : id(i), inputCode(ic), description(desc), type(kHardwareInputTypeGeneric) { } + + HardwareInput(String i, KeyState ky, String desc = "") + : id(i), key(ky), description(desc), type(kHardwareInputTypeKeyboard) { } +}; + +struct HardwareInputTableEntry { + const char *hwId; + HardwareInputCode code; + const char *desc; }; /** @@ -97,6 +125,8 @@ public: const HardwareInput *findHardwareInput(String id) const; + const HardwareInput *findHardwareInput(const HardwareInputCode code) const; + const HardwareInput *findHardwareInput(const KeyState& keystate) const; const List<const HardwareInput *> &getHardwareInputs() const { return _inputs; } @@ -104,18 +134,17 @@ public: uint size() const { return _inputs.size(); } /** - * Add hardware inputs to the set out of key and modifier tables. - * @param keys table of available keys - * @param modifiers table of available modifiers + * Add hardware inputs to the set out of a table. + * @param inputs table of available inputs */ - void addHardwareInputs(const KeyTableEntry keys[], const ModifierTableEntry modifiers[]); + void addHardwareInputs(const HardwareInputTableEntry inputs[]); /** - * Add hardware inputs to the set out of a key table. - * The default modifiers are applied to the key entries + * Add hardware inputs to the set out of key and modifier tables. * @param keys table of available keys + * @param modifiers table of available modifiers */ - void addHardwareInputs(const KeyTableEntry keys[]); + void addHardwareInputs(const KeyTableEntry keys[], const ModifierTableEntry modifiers[]); void removeHardwareInput(const HardwareInput *input); diff --git a/backends/keymapper/keymap.cpp b/backends/keymapper/keymap.cpp index 8ea975c927..e95dd6afb5 100644 --- a/backends/keymapper/keymap.cpp +++ b/backends/keymapper/keymap.cpp @@ -33,14 +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(); if (hwInput) { - _keymap[hwInput->key] = *it; + if (hwInput->type == kHardwareInputTypeKeyboard) + _keymap[hwInput->key] = *it; + else if (hwInput->type == kHardwareInputTypeGeneric) + _nonkeymap[hwInput->inputCode] = *it; } } } @@ -60,23 +63,31 @@ void Keymap::addAction(Action *action) { } void Keymap::registerMapping(Action *action, const HardwareInput *hwInput) { - HashMap<KeyState, Action *>::iterator it; - - 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) { - it->_value->mapInput(0); + if (hwInput->type == kHardwareInputTypeKeyboard) { + 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; } - - _keymap[hwInput->key] = action; } void Keymap::unregisterMapping(Action *action) { const HardwareInput *hwInput = action->getMappedInput(); if (hwInput) { - _keymap.erase(hwInput->key); + if (hwInput->type == kHardwareInputTypeKeyboard) + _keymap.erase(hwInput->key); + else if (hwInput->type == kHardwareInputTypeGeneric) + _nonkeymap.erase(hwInput->inputCode); } } @@ -116,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 bda4cd47da..dcb021f2d8 100644 --- a/backends/keymapper/keymapper.cpp +++ b/backends/keymapper/keymapper.cpp @@ -25,9 +25,14 @@ #ifdef ENABLE_KEYMAPPER #include "common/config-manager.h" +#include "common/system.h" namespace Common { +// These magic numbers are provided by fuzzie and WebOS +static const uint32 kDelayKeyboardEventMillis = 250; +static const uint32 kDelayMouseEventMillis = 50; + void Keymapper::Domain::addKeymap(Keymap *map) { iterator it = find(map->getName()); @@ -54,7 +59,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 +188,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 +205,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 +251,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,56 +283,108 @@ 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; - + Event evt; 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; + 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); + + // Check if the event is coming from a non-key hardware event + // that is mapped to a key event + if (incomingType == kIncomingNonKey && convertedType != EVENT_INVALID) + // WORKAROUND: Delay the down events coming from non-key hardware events + // with a zero delay. This is to prevent DOWN1 DOWN2 UP1 UP2. + addDelayedEvent(0, evt); + else + mappedEvents.push_back(evt); + + // non-keys need to send up as well + if (incomingType == kIncomingNonKey && convertedType != EVENT_INVALID) { + // WORKAROUND: Delay the up events coming from non-key hardware events + // This is for engines that run scripts that check on key being down + evt.type = convertedType; + const uint32 delay = (convertedType == EVENT_KEYUP ? kDelayKeyboardEventMillis : kDelayMouseEventMillis); + addDelayedEvent(delay, 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; } +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 daa746f379..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,16 +169,45 @@ 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); + /** + * Return a HardwareInput pointer for the given input code + */ + const HardwareInput *findHardwareInput(const HardwareInputCode code); + Domain& getGlobalDomain() { return _globalDomain; } Domain& getGameDomain() { return _gameDomain; } const Stack<MapRecord>& getActiveStack() const { return _activeMaps; } private: + enum IncomingEventType { + kIncomingKeyDown, + kIncomingKeyUp, + kIncomingNonKey + }; + void initKeymap(Domain &domain, Keymap *keymap); Domain _globalDomain; @@ -188,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 dab295219a..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(); } @@ -354,9 +351,14 @@ void RemapDialog::loadKeymap() { Keymapper::MapRecord mr = activeKeymaps[i]; debug(3, "RemapDialog::loadKeymap keymap: %s", mr.keymap->getName().c_str()); List<const HardwareInput *>::iterator inputIt = freeInputs.begin(); + const HardwareInput *input = *inputIt; while (inputIt != freeInputs.end()) { - Action *act = mr.keymap->getMappedAction((*inputIt)->key); + Action *act = 0; + 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; diff --git a/common/EventDispatcher.cpp b/common/EventDispatcher.cpp index 4c7286bbb5..012a2dfce5 100644 --- a/common/EventDispatcher.cpp +++ b/common/EventDispatcher.cpp @@ -60,6 +60,12 @@ void EventDispatcher::dispatch() { } } } + + List<Event> delayedEvents = _mapper->getDelayedEvents(); + for (List<Event>::iterator k = delayedEvents.begin(); k != delayedEvents.end(); ++k) { + const Event delayedEvent = *k; + dispatchEvent(delayedEvent); + } } void EventDispatcher::registerMapper(EventMapper *mapper) { diff --git a/common/EventMapper.cpp b/common/EventMapper.cpp index 2808a7b5fd..47db61e472 100644 --- a/common/EventMapper.cpp +++ b/common/EventMapper.cpp @@ -22,6 +22,9 @@ #include "common/events.h" +#include "common/system.h" +#include "common/textconsole.h" + namespace Common { List<Event> DefaultEventMapper::mapEvent(const Event &ev, EventSource *source) { @@ -46,9 +49,44 @@ List<Event> DefaultEventMapper::mapEvent(const Event &ev, EventSource *source) { // if it didn't get mapped, just pass it through if (mappedEvent.type == EVENT_INVALID) mappedEvent = ev; + +#ifdef ENABLE_VKEYBD + // TODO: this check is not needed post-split + if (mappedEvent.type == EVENT_CUSTOM_BACKEND_HARDWARE) { + warning("EVENT_CUSTOM_BACKEND_HARDWARE was not mapped"); + return List<Event>(); + } +#endif + events.push_back(mappedEvent); return events; } +void DefaultEventMapper::addDelayedEvent(uint32 millis, Event ev) { + if (_delayedEvents.empty()) { + _delayedEffectiveTime = g_system->getMillis() + millis; + millis = 0; + } + DelayedEventsEntry entry = DelayedEventsEntry(millis, ev); + _delayedEvents.push(entry); +} + +List<Event> DefaultEventMapper::getDelayedEvents() { + List<Event> events; + + if (_delayedEvents.empty()) + return events; + + uint32 now = g_system->getMillis(); + + while (!_delayedEvents.empty() && now >= _delayedEffectiveTime) { + DelayedEventsEntry entry = _delayedEvents.pop(); + if (!_delayedEvents.empty()) + _delayedEffectiveTime += _delayedEvents.front().timerOffset; + events.push_back(entry.event); + } + return events; +} + } // namespace Common diff --git a/common/events.h b/common/events.h index 4efdd67b91..7366c51d36 100644 --- a/common/events.h +++ b/common/events.h @@ -79,6 +79,8 @@ enum EventType { // IMPORTANT NOTE: This is part of the WIP Keymapper. If you plan to use // this, please talk to tsoliman and/or LordHoto. EVENT_CUSTOM_BACKEND_ACTION = 18, + EVENT_CUSTOM_BACKEND_HARDWARE = 21, + EVENT_GUI_REMAP_COMPLETE_ACTION = 22, EVENT_KEYMAPPER_REMAP = 19 #endif #ifdef ENABLE_VKEYBD @@ -230,12 +232,27 @@ public: * Map an incoming event to one or more action events */ virtual List<Event> mapEvent(const Event &ev, EventSource *source) = 0; + + virtual List<Event> getDelayedEvents() = 0; }; class DefaultEventMapper : public EventMapper { public: + DefaultEventMapper() : _delayedEvents(), _delayedEffectiveTime(0) {} // EventMapper interface virtual List<Event> mapEvent(const Event &ev, EventSource *source); + virtual List<Event> getDelayedEvents(); +protected: + virtual void addDelayedEvent(uint32 millis, Event ev); + + struct DelayedEventsEntry { + const uint32 timerOffset; + const Event event; + DelayedEventsEntry(const uint32 offset, const Event ev) : timerOffset(offset), event(ev) { } + }; + + Queue<DelayedEventsEntry> _delayedEvents; + uint32 _delayedEffectiveTime; }; /** diff --git a/gui/dialog.cpp b/gui/dialog.cpp index fd15ba5e09..2201e83ca5 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -21,6 +21,10 @@ #include "common/rect.h" +#ifdef ENABLE_KEYMAPPER +#include "common/events.h" +#endif + #include "gui/gui-manager.h" #include "gui/dialog.h" #include "gui/widget.h" @@ -314,6 +318,9 @@ void Dialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { } } +#ifdef ENABLE_KEYMAPPER +void Dialog::handleOtherEvent(Common::Event evt) { } +#endif /* * Determine the widget at location (x,y) if any. Assumes the coordinates are * in the local coordinate system, i.e. relative to the top left of the dialog. diff --git a/gui/dialog.h b/gui/dialog.h index a324450996..f5a5f94a68 100644 --- a/gui/dialog.h +++ b/gui/dialog.h @@ -29,6 +29,12 @@ #include "gui/object.h" #include "gui/ThemeEngine.h" +#ifdef ENABLE_KEYMAPPER +namespace Common { +struct Event; +} +#endif + namespace GUI { class Widget; @@ -82,6 +88,9 @@ protected: virtual void handleKeyUp(Common::KeyState state); virtual void handleMouseMoved(int x, int y, int button); virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); +#ifdef ENABLE_KEYMAPPER + virtual void handleOtherEvent(Common::Event evt); +#endif Widget *findWidget(int x, int y); // Find the widget at pos x,y if any Widget *findWidget(const char *name); diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp index 4fa60bfe07..ffecd928bc 100644 --- a/gui/gui-manager.cpp +++ b/gui/gui-manager.cpp @@ -366,6 +366,9 @@ void GuiManager::runLoop() { screenChange(); break; default: +#ifdef ENABLE_KEYMAPPER + activeDialog->handleOtherEvent(event); +#endif break; } |