diff options
| author | Eugene Sandulenko | 2012-03-17 03:46:46 -0700 | 
|---|---|---|
| committer | Eugene Sandulenko | 2012-03-17 03:46:46 -0700 | 
| commit | 56252909f5bebfa9cfd43cf092effb0111fdabef (patch) | |
| tree | efcf99fefc8b019cd07c119a9e15ccf3be06a2fe | |
| parent | 5ae2543795433513e68339b16e0783d4b3295204 (diff) | |
| parent | c0a215282d12872cf32fb24f9067216c0f869b96 (diff) | |
| download | scummvm-rg350-56252909f5bebfa9cfd43cf092effb0111fdabef.tar.gz scummvm-rg350-56252909f5bebfa9cfd43cf092effb0111fdabef.tar.bz2 scummvm-rg350-56252909f5bebfa9cfd43cf092effb0111fdabef.zip  | |
Merge pull request #202 from tsoliman/keymapper-nonkey-inputs
KEYMAPPER: Add Gesture Support
| -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;  			}  | 
