[Scummvm-git-logs] scummvm master -> b3345e79a9f5d5b5b94ecadbfd3e9ff634bbb7af

bgK bastien.bouclet at gmail.com
Wed Jan 29 08:04:42 UTC 2020


This automated email contains information about 29 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
2d7588d9c3 EVENTS: Remove the dependency to EventSource from EventMapper
cc336635a1 KEYMAPPER: Change custom backend action events not to be instant
14663c4790 KEYMAPPER: Make the keymapper mandatory
d2f09a4bfc BUILD: Don't build the event recorder by default
ec9c394787 KEYMAPPER: Remove DefaultEventMapper
7617723ab5 KEYMAPPER: Allow backends to register multiple keymaps
c131e8f5b9 EVENTS: Use the keymapper for some previously hard-coded key bindings
be49fc4b9a SDL: Add a keymap for the graphics manager
13fbdb935a KEYMAPPER: Use custom backend actions for the SDL graphics keymap
df4bf6556c KEYMAPPER: Introduce custom engine actions
0995f40677 MOHAWK: RIVEN: Use custom engine actions for event handing
df7ce0c55f KEYMAPPER: Rework HardwareInputSet not to allocate all possible inputs
85f476070b PEGASUS: Use custom engine actions for key input
32174c9067 KEYMAPPER: Actions can now be bound to joystick buttons
376a77e735 PEGASUS: Add default joystick action bindings
426867f4bc KEYMAPPER: Give human readable descriptions to the keymaps
519b4a57e2 KEYMAPPER: Allow engines to return multiple keymaps
e973092aef KEYMAPPER: Enable remapping of the mouse buttons
7ecccd3b30 MOHAWK: RIVEN: Add default joystick action mappings
c001094bce KEYMAPPER: Add a button in the remap dialog to reset an entire keymap
17a13c9294 KEYMAPPER: Shorten the name of some joystick inputs
5079fa9dd4 KEYMAPPER: Sort the mappings by type and id in the remap dialog
cc15496e9e KEYMAPPER: Use a dropdown button to save horizontal space
5106563c65 MOHAWK: MYST: Add a keymap
43184657e9 EVENTS: Disable ScummVM's source of keyboard repeat events by default
2ef7365401 KEYMAPPER: Change backend default bindings to replace keymap defaults
78ab571519 3DS: Update the port to take advantage of the new keymapper
05a7ca7b76 PS3: Use the appropriate gamepad button names for the keymapper
b3345e79a9 I18N: Update POTFILES for the keymapper changes


Commit: 2d7588d9c3ac0677a87e67285c10c557fee39970
    https://github.com/scummvm/scummvm/commit/2d7588d9c3ac0677a87e67285c10c557fee39970
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
EVENTS: Remove the dependency to EventSource from EventMapper

Changed paths:
    backends/keymapper/keymapper.cpp
    backends/keymapper/keymapper.h
    common/EventDispatcher.cpp
    common/EventMapper.cpp
    common/events.h


diff --git a/backends/keymapper/keymapper.cpp b/backends/keymapper/keymapper.cpp
index f9e595b..7de4b1b 100644
--- a/backends/keymapper/keymapper.cpp
+++ b/backends/keymapper/keymapper.cpp
@@ -138,17 +138,14 @@ void Keymapper::setEnabledKeymapType(Keymap::KeymapType type) {
 	_enabledKeymapType = type;
 }
 
-List<Event> Keymapper::mapEvent(const Event &ev, EventSource *source) {
+List<Event> Keymapper::mapEvent(const Event &ev) {
 	if (!_enabled) {
-		return DefaultEventMapper::mapEvent(ev, source);
-	}
-	if (source && !source->allowMapping()) {
-		return DefaultEventMapper::mapEvent(ev, source);
+		return DefaultEventMapper::mapEvent(ev);
 	}
 
 	const HardwareInput *hwInput = findHardwareInput(ev);
 	if (!hwInput) {
-		return DefaultEventMapper::mapEvent(ev, source);
+		return DefaultEventMapper::mapEvent(ev);
 	}
 
 	IncomingEventType incomingEventType = convertToIncomingEventType(ev);
@@ -178,7 +175,7 @@ List<Event> Keymapper::mapEvent(const Event &ev, EventSource *source) {
 	}
 
 	if (mappedEvents.empty()) {
-		return DefaultEventMapper::mapEvent(ev, source);
+		return DefaultEventMapper::mapEvent(ev);
 	}
 
 	return mappedEvents;
diff --git a/backends/keymapper/keymapper.h b/backends/keymapper/keymapper.h
index 8770499..920de70 100644
--- a/backends/keymapper/keymapper.h
+++ b/backends/keymapper/keymapper.h
@@ -52,7 +52,7 @@ public:
 	~Keymapper();
 
 	// EventMapper interface
-	virtual List<Event> mapEvent(const Event &ev, EventSource *source);
+	virtual List<Event> mapEvent(const Event &ev);
 
 	/**
 	 * Registers a HardwareInputSet with the Keymapper
diff --git a/common/EventDispatcher.cpp b/common/EventDispatcher.cpp
index 259c233..c8d8a45 100644
--- a/common/EventDispatcher.cpp
+++ b/common/EventDispatcher.cpp
@@ -53,12 +53,17 @@ void EventDispatcher::dispatch() {
 		while (i->source->pollEvent(event)) {
 			// We only try to process the events via the setup event mapper, when
 			// we have a setup mapper and when the event source allows mapping.
-			assert(_mapper);
-			List<Event> mappedEvents = _mapper->mapEvent(event, i->source);
+			if (i->source->allowMapping()) {
+				assert(_mapper);
 
-			for (List<Event>::iterator j = mappedEvents.begin(); j != mappedEvents.end(); ++j) {
-				const Event mappedEvent = *j;
-				dispatchEvent(mappedEvent);
+				List<Event> mappedEvents = _mapper->mapEvent(event);
+
+				for (List<Event>::iterator j = mappedEvents.begin(); j != mappedEvents.end(); ++j) {
+					const Event mappedEvent = *j;
+					dispatchEvent(mappedEvent);
+				}
+			} else {
+				dispatchEvent(event);
 			}
 		}
 	}
diff --git a/common/EventMapper.cpp b/common/EventMapper.cpp
index 7693ace..6cb5e52 100644
--- a/common/EventMapper.cpp
+++ b/common/EventMapper.cpp
@@ -27,7 +27,7 @@
 
 namespace Common {
 
-List<Event> DefaultEventMapper::mapEvent(const Event &ev, EventSource *source) {
+List<Event> DefaultEventMapper::mapEvent(const Event &ev) {
 	List<Event> events;
 	Event mappedEvent;
 #ifdef ENABLE_VKEYBD
diff --git a/common/events.h b/common/events.h
index 22b4743..c36c571 100644
--- a/common/events.h
+++ b/common/events.h
@@ -291,7 +291,7 @@ public:
 	/**
 	 * Map an incoming event to one or more action events
 	 */
-	virtual List<Event> mapEvent(const Event &ev, EventSource *source) = 0;
+	virtual List<Event> mapEvent(const Event &ev) = 0;
 
 	virtual List<Event> getDelayedEvents() = 0;
 };
@@ -300,7 +300,7 @@ class DefaultEventMapper : public EventMapper {
 public:
 	DefaultEventMapper() : _delayedEvents(), _delayedEffectiveTime(0) {}
 	// EventMapper interface
-	virtual List<Event> mapEvent(const Event &ev, EventSource *source);
+	virtual List<Event> mapEvent(const Event &ev);
 	virtual List<Event> getDelayedEvents();
 protected:
 	virtual void addDelayedEvent(uint32 millis, Event ev);


Commit: cc336635a16e8fcc0c46e6460b961477b950be71
    https://github.com/scummvm/scummvm/commit/cc336635a16e8fcc0c46e6460b961477b950be71
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
KEYMAPPER: Change custom backend action events not to be instant

Allows action consumers to choose if they want to react on the start or
on the end of an user interaction.

Changed paths:
    backends/events/maemosdl/maemosdl-events.cpp
    backends/keymapper/keymapper.cpp
    backends/keymapper/keymapper.h
    backends/platform/maemo/maemo.cpp
    common/EventDispatcher.cpp
    common/events.h


diff --git a/backends/events/maemosdl/maemosdl-events.cpp b/backends/events/maemosdl/maemosdl-events.cpp
index 13677a6..8f8b2bd 100644
--- a/backends/events/maemosdl/maemosdl-events.cpp
+++ b/backends/events/maemosdl/maemosdl-events.cpp
@@ -190,7 +190,7 @@ MaemoSdlEventObserver::MaemoSdlEventObserver(MaemoSdlEventSource *eventSource) {
 
 bool MaemoSdlEventObserver::notifyEvent(const Common::Event &event) {
 #ifdef ENABLE_KEYMAPPER
-	if (event.type != Common::EVENT_CUSTOM_BACKEND_ACTION)
+	if (event.type != Common::EVENT_CUSTOM_BACKEND_ACTION_START)
 		return false;
 	if (event.customType == kEventClickMode) {
 		assert(_eventSource);
diff --git a/backends/keymapper/keymapper.cpp b/backends/keymapper/keymapper.cpp
index 7de4b1b..d7c0869 100644
--- a/backends/keymapper/keymapper.cpp
+++ b/backends/keymapper/keymapper.cpp
@@ -183,20 +183,20 @@ List<Event> Keymapper::mapEvent(const Event &ev) {
 
 Keymapper::IncomingEventType Keymapper::convertToIncomingEventType(const Event &ev) const {
 	if (ev.type == EVENT_CUSTOM_BACKEND_HARDWARE) {
-		return kIncomingNonKey;
+		return kIncomingEventInstant;
 	} else if (ev.type == EVENT_KEYDOWN) {
-		return kIncomingKeyDown;
+		return kIncomingEventStart;
 	} else {
-		return kIncomingKeyUp;
+		return kIncomingEventEnd;
 	}
 }
 
 Event Keymapper::executeAction(const Action *action, IncomingEventType incomingType) {
 	Event evt = Event(action->event);
-	EventType convertedType = convertDownToUp(evt.type);
+	EventType convertedType = convertStartToEnd(evt.type);
 
 	// hardware keys need to send up instead when they are up
-	if (incomingType == kIncomingKeyUp) {
+	if (incomingType == kIncomingEventEnd) {
 		evt.type = convertedType;
 	}
 
@@ -204,7 +204,7 @@ Event Keymapper::executeAction(const Action *action, IncomingEventType incomingT
 
 	// 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) {
+	if (incomingType == kIncomingEventInstant && 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);
@@ -220,7 +220,7 @@ Event Keymapper::executeAction(const Action *action, IncomingEventType incomingT
 	return evt;
 }
 
-EventType Keymapper::convertDownToUp(EventType type) {
+EventType Keymapper::convertStartToEnd(EventType type) {
 	EventType result = EVENT_INVALID;
 	switch (type) {
 	case EVENT_KEYDOWN:
@@ -235,6 +235,9 @@ EventType Keymapper::convertDownToUp(EventType type) {
 	case EVENT_MBUTTONDOWN:
 		result = EVENT_MBUTTONUP;
 		break;
+	case EVENT_CUSTOM_BACKEND_ACTION_START:
+		result = EVENT_CUSTOM_BACKEND_ACTION_END;
+		break;
 	default:
 		break;
 	}
diff --git a/backends/keymapper/keymapper.h b/backends/keymapper/keymapper.h
index 920de70..3c89ce7 100644
--- a/backends/keymapper/keymapper.h
+++ b/backends/keymapper/keymapper.h
@@ -129,16 +129,16 @@ public:
 private:
 
 	enum IncomingEventType {
-		kIncomingKeyDown,
-		kIncomingKeyUp,
-		kIncomingNonKey
+		kIncomingEventStart,
+		kIncomingEventEnd,
+		kIncomingEventInstant
 	};
 
 	HardwareInputSet *_hardwareInputs;
 	const KeymapperDefaultBindings *_backendDefaultBindings;
 
 	Event executeAction(const Action *act, IncomingEventType incomingType);
-	EventType convertDownToUp(EventType eventType);
+	EventType convertStartToEnd(EventType eventType);
 	IncomingEventType convertToIncomingEventType(const Event &ev) const;
 
 	EventManager *_eventMan;
diff --git a/backends/platform/maemo/maemo.cpp b/backends/platform/maemo/maemo.cpp
index e0cf0e6..60a940c 100644
--- a/backends/platform/maemo/maemo.cpp
+++ b/backends/platform/maemo/maemo.cpp
@@ -204,7 +204,7 @@ Common::Keymap *OSystem_SDL_Maemo::getGlobalKeymap() {
 
 	act = new Action("CLKM", _("Click Mode"));
 	Event evt = Event();
-	evt.type = EVENT_CUSTOM_BACKEND_ACTION;
+	evt.type = EVENT_CUSTOM_BACKEND_ACTION_START;
 	evt.customType = Maemo::kEventClickMode;
 	act->setEvent(evt);
 	globalMap->addAction(act);
diff --git a/common/EventDispatcher.cpp b/common/EventDispatcher.cpp
index c8d8a45..f380146 100644
--- a/common/EventDispatcher.cpp
+++ b/common/EventDispatcher.cpp
@@ -56,6 +56,11 @@ void EventDispatcher::dispatch() {
 			if (i->source->allowMapping()) {
 				assert(_mapper);
 
+				// Backends may not produce directly action event types, those are meant
+				// to be the output of the event mapper.
+				assert(event.type != EVENT_CUSTOM_BACKEND_ACTION_START);
+				assert(event.type != EVENT_CUSTOM_BACKEND_ACTION_END);
+
 				List<Event> mappedEvents = _mapper->mapEvent(event);
 
 				for (List<Event>::iterator j = mappedEvents.begin(); j != mappedEvents.end(); ++j) {
diff --git a/common/events.h b/common/events.h
index c36c571..b392b6e 100644
--- a/common/events.h
+++ b/common/events.h
@@ -77,7 +77,8 @@ enum EventType {
 #ifdef ENABLE_KEYMAPPER
 	// 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_ACTION_START = 18,
+	EVENT_CUSTOM_BACKEND_ACTION_END = 19,
 	EVENT_CUSTOM_BACKEND_HARDWARE = 21,
 #endif
 #ifdef ENABLE_VKEYBD


Commit: 14663c4790902031684d40cda5334e7914cffb24
    https://github.com/scummvm/scummvm/commit/14663c4790902031684d40cda5334e7914cffb24
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
KEYMAPPER: Make the keymapper mandatory

Changed paths:
    backends/events/default/default-events.cpp
    backends/events/default/default-events.h
    backends/events/maemosdl/maemosdl-events.cpp
    backends/keymapper/action.cpp
    backends/keymapper/action.h
    backends/keymapper/hardware-input.cpp
    backends/keymapper/hardware-input.h
    backends/keymapper/input-watcher.cpp
    backends/keymapper/input-watcher.h
    backends/keymapper/keymap.cpp
    backends/keymapper/keymap.h
    backends/keymapper/keymapper-defaults.h
    backends/keymapper/keymapper.cpp
    backends/keymapper/keymapper.h
    backends/keymapper/remap-widget.cpp
    backends/keymapper/remap-widget.h
    backends/module.mk
    backends/platform/androidsdl/androidsdl-sdl.h
    backends/platform/linuxmoto/hardwarekeys.cpp
    backends/platform/linuxmoto/linuxmoto-sdl.h
    backends/platform/maemo/maemo.cpp
    backends/platform/maemo/maemo.h
    backends/platform/symbian/src/portdefs.h
    base/main.cpp
    base/version.cpp
    common/EventMapper.cpp
    common/config-manager.cpp
    common/config-manager.h
    common/events.h
    common/system.h
    configure
    devtools/create_project/create_project.cpp
    engines/kyra/engine/eobcommon.cpp
    engines/kyra/engine/lol.cpp
    engines/kyra/gui/gui_eob.cpp
    engines/kyra/gui/gui_lol.cpp
    engines/metaengine.cpp
    engines/mohawk/riven.cpp
    engines/pegasus/pegasus.cpp
    gui/editgamedialog.cpp
    gui/gui-manager.cpp
    gui/options.cpp


diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp
index ae782bb..2a148bc 100644
--- a/backends/events/default/default-events.cpp
+++ b/backends/events/default/default-events.cpp
@@ -57,14 +57,10 @@ DefaultEventManager::DefaultEventManager(Common::EventSource *boss) :
 #ifdef ENABLE_VKEYBD
 	_vk = nullptr;
 #endif
-#ifdef ENABLE_KEYMAPPER
 	_keymapper = new Common::Keymapper(this);
 	// EventDispatcher will automatically free the keymapper
 	_dispatcher.registerMapper(_keymapper);
 	_remap = false;
-#else
-	_dispatcher.registerMapper(new Common::DefaultEventMapper());
-#endif
 }
 
 DefaultEventManager::~DefaultEventManager() {
@@ -304,8 +300,6 @@ void DefaultEventManager::purgeMouseEvents() {
 	_eventQueue = filteredQueue;
 }
 
-#ifdef ENABLE_KEYMAPPER
-
 Common::Keymap *DefaultEventManager::getGlobalKeymap() {
 	using namespace Common;
 
@@ -345,6 +339,4 @@ Common::Keymap *DefaultEventManager::getGlobalKeymap() {
 	return globalKeymap;
 }
 
-#endif
-
 #endif // !defined(DISABLE_DEFAULT_EVENTMANAGER)
diff --git a/backends/events/default/default-events.h b/backends/events/default/default-events.h
index ed25a2d..11d523a 100644
--- a/backends/events/default/default-events.h
+++ b/backends/events/default/default-events.h
@@ -27,9 +27,7 @@
 #include "common/queue.h"
 
 namespace Common {
-#ifdef ENABLE_KEYMAPPER
 class Keymapper;
-#endif
 #ifdef ENABLE_VKEYBD
 class VirtualKeyboard;
 #endif
@@ -41,10 +39,8 @@ class DefaultEventManager : public Common::EventManager, Common::EventObserver {
 	Common::VirtualKeyboard *_vk;
 #endif
 
-#ifdef ENABLE_KEYMAPPER
 	Common::Keymapper *_keymapper;
 	bool _remap;
-#endif
 
 	Common::ArtificialEventSource _artificialEventSource;
 
@@ -91,12 +87,8 @@ public:
 	virtual void resetQuit() override { _shouldQuit = false; }
 #endif
 
-#ifdef ENABLE_KEYMAPPER
-	 // IMPORTANT NOTE: This is part of the WIP Keymapper. If you plan to use
-	 // this, please talk to tsoliman and/or LordHoto.
 	Common::Keymapper *getKeymapper() override { return _keymapper; }
 	Common::Keymap *getGlobalKeymap() override;
-#endif
 
 	/**
 	 * Controls whether repeated key down events are generated while a key is pressed
diff --git a/backends/events/maemosdl/maemosdl-events.cpp b/backends/events/maemosdl/maemosdl-events.cpp
index 8f8b2bd..9354094 100644
--- a/backends/events/maemosdl/maemosdl-events.cpp
+++ b/backends/events/maemosdl/maemosdl-events.cpp
@@ -61,7 +61,6 @@ bool MaemoSdlEventSource::remapKey(SDL_Event &ev, Common::Event &event) {
 	// SDLK_F7 -> zoom +
 	// SDLK_F8 -> zoom -
 
-#ifdef ENABLE_KEYMAPPER
 	if (ev.type == SDL_KEYDOWN || ev.type == SDL_KEYUP) {
 		const KeymapEntry *entry;
 		for (entry = keymapEntries; entry->sym != SDLK_LAST; ++entry) {
@@ -74,83 +73,7 @@ bool MaemoSdlEventSource::remapKey(SDL_Event &ev, Common::Event &event) {
 			}
 		}
 	}
-#else
-	switch (ev.type) {
-		case SDL_KEYDOWN:{
-			if (ev.key.keysym.sym == SDLK_F4
-			    || (model.modelType == kModelTypeN900
-			        && ev.key.keysym.sym == SDLK_m
-			        && (ev.key.keysym.mod & KMOD_CTRL)
-			        && (ev.key.keysym.mod & KMOD_SHIFT))) {
-				event.type = Common::EVENT_MAINMENU;
-				debug(9, "remapping to main menu");
-				return true;
-			} else if (ev.key.keysym.sym == SDLK_F6) {
-				if (!model.hasHwKeyboard) {
-#ifdef ENABLE_VKEYBD
-					event.type = Common::EVENT_VIRTUAL_KEYBOARD;
-					debug(9, "remapping to virtual keyboard trigger");
-					return true;
-#endif
-				} else {
-					// handled in keyup
-				}
-			} else if (ev.key.keysym.sym == SDLK_F7) {
-				event.type = Common::EVENT_RBUTTONDOWN;
-				processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
-				 debug(9, "remapping to right click down");
-				return true;
-			} else if (ev.key.keysym.sym == SDLK_F8) {
-				if (ev.key.keysym.mod & KMOD_CTRL) {
-#ifdef ENABLE_VKEYBD
-					event.type = Common::EVENT_VIRTUAL_KEYBOARD;
-					debug(9, "remapping to virtual keyboard trigger");
-					return true;
-#endif
-				} else {
-					// handled in keyup
-					return true;
-				}
-			}
-			break;
-		}
-		case SDL_KEYUP: {
-			if (ev.key.keysym.sym == SDLK_F4
-			    || (model.modelType == kModelTypeN900
-			        && ev.key.keysym.sym == SDLK_m
-			        && (ev.key.keysym.mod & KMOD_CTRL)
-			        && (ev.key.keysym.mod & KMOD_SHIFT))) {
-				event.type = Common::EVENT_MAINMENU;
-				return true;
-			} else if (ev.key.keysym.sym == SDLK_F6) {
-				if (!model.hasHwKeyboard) {
-					// handled in keydown
-				} else {
-					bool currentState = ((OSystem_SDL *)g_system)->getGraphicsManager()->getFeatureState(OSystem::kFeatureFullscreenMode);
-					g_system->beginGFXTransaction();
-					((OSystem_SDL *)g_system)->getGraphicsManager()->setFeatureState(OSystem::kFeatureFullscreenMode, !currentState);
-					g_system->endGFXTransaction();
-					debug(9, "remapping to full screen toggle");
-					return true;
-				}
-			} else if (ev.key.keysym.sym == SDLK_F7) {
-				event.type = Common::EVENT_RBUTTONUP;
-				processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
-					debug(9, "remapping to right click up");
-				return true;
-			} else if (ev.key.keysym.sym == SDLK_F8) {
-				if (ev.key.keysym.mod & KMOD_CTRL) {
-					// handled in key down
-				} else {
-					toggleClickMode();
-					debug(9, "remapping to click toggle");
-					return true;
-				}
-			}
-			break;
-		}
-	}
-#endif
+
 	// Invoke parent implementation of this method
 	return SdlEventSource::remapKey(ev, event);
 }
@@ -189,7 +112,6 @@ MaemoSdlEventObserver::MaemoSdlEventObserver(MaemoSdlEventSource *eventSource) {
 }
 
 bool MaemoSdlEventObserver::notifyEvent(const Common::Event &event) {
-#ifdef ENABLE_KEYMAPPER
 	if (event.type != Common::EVENT_CUSTOM_BACKEND_ACTION_START)
 		return false;
 	if (event.customType == kEventClickMode) {
@@ -197,7 +119,6 @@ bool MaemoSdlEventObserver::notifyEvent(const Common::Event &event) {
 		_eventSource->toggleClickMode();
 		return true;
 	}
-#endif
 	return false;
 }
 
diff --git a/backends/keymapper/action.cpp b/backends/keymapper/action.cpp
index 0b7b67a..4c8904d 100644
--- a/backends/keymapper/action.cpp
+++ b/backends/keymapper/action.cpp
@@ -22,8 +22,6 @@
 
 #include "backends/keymapper/action.h"
 
-#ifdef ENABLE_KEYMAPPER
-
 #include "backends/keymapper/keymap.h"
 
 namespace Common {
@@ -43,5 +41,3 @@ void Action::addDefaultInputMapping(const String &hwId) {
 }
 
 } // End of namespace Common
-
-#endif // #ifdef ENABLE_KEYMAPPER
diff --git a/backends/keymapper/action.h b/backends/keymapper/action.h
index 701ae35..c777cda 100644
--- a/backends/keymapper/action.h
+++ b/backends/keymapper/action.h
@@ -25,8 +25,6 @@
 
 #include "common/scummsys.h"
 
-#ifdef ENABLE_KEYMAPPER
-
 #include "common/array.h"
 #include "common/events.h"
 #include "common/str.h"
@@ -101,6 +99,4 @@ public:
 
 } // End of namespace Common
 
-#endif // #ifdef ENABLE_KEYMAPPER
-
 #endif // #ifndef COMMON_ACTION_H
diff --git a/backends/keymapper/hardware-input.cpp b/backends/keymapper/hardware-input.cpp
index 86d70a1..fc27b1e 100644
--- a/backends/keymapper/hardware-input.cpp
+++ b/backends/keymapper/hardware-input.cpp
@@ -22,8 +22,6 @@
 
 #include "backends/keymapper/hardware-input.h"
 
-#ifdef ENABLE_KEYMAPPER
-
 #include "backends/keymapper/keymapper.h"
 
 namespace Common {
@@ -303,6 +301,3 @@ void HardwareInputSet::addHardwareInputs(const KeyTableEntry keys[], const Modif
 }
 
 } //namespace Common
-
-#endif // #ifdef ENABLE_KEYMAPPER
-
diff --git a/backends/keymapper/hardware-input.h b/backends/keymapper/hardware-input.h
index eda7661..07d42bd 100644
--- a/backends/keymapper/hardware-input.h
+++ b/backends/keymapper/hardware-input.h
@@ -25,9 +25,6 @@
 
 #include "common/scummsys.h"
 
-#ifdef ENABLE_KEYMAPPER
-
-#include "common/array.h"
 #include "common/hashmap.h"
 #include "common/keyboard.h"
 #include "common/str.h"
@@ -160,6 +157,4 @@ private:
 
 } // End of namespace Common
 
-#endif // #ifdef ENABLE_KEYMAPPER
-
 #endif // #ifndef COMMON_HARDWARE_KEY_H
diff --git a/backends/keymapper/input-watcher.cpp b/backends/keymapper/input-watcher.cpp
index c457931..0dc989b 100644
--- a/backends/keymapper/input-watcher.cpp
+++ b/backends/keymapper/input-watcher.cpp
@@ -22,8 +22,6 @@
 
 #include "backends/keymapper/input-watcher.h"
 
-#ifdef ENABLE_KEYMAPPER
-
 #include "backends/keymapper/action.h"
 #include "backends/keymapper/keymapper.h"
 
@@ -84,5 +82,3 @@ const HardwareInput *InputWatcher::checkForCapturedInput() {
 }
 
 } // End of namespace Common
-
-#endif // #ifdef ENABLE_KEYMAPPER
diff --git a/backends/keymapper/input-watcher.h b/backends/keymapper/input-watcher.h
index 2f5e167..5818fe6 100644
--- a/backends/keymapper/input-watcher.h
+++ b/backends/keymapper/input-watcher.h
@@ -25,8 +25,6 @@
 
 #include "common/scummsys.h"
 
-#ifdef ENABLE_KEYMAPPER
-
 #include "common/events.h"
 
 namespace Common {
@@ -64,6 +62,4 @@ private:
 
 } // End of namespace Common
 
-#endif // #ifdef ENABLE_KEYMAPPER
-
 #endif // #ifndef COMMON_INPUT_WATCHER_H
diff --git a/backends/keymapper/keymap.cpp b/backends/keymapper/keymap.cpp
index 2e99a44..38b70e8 100644
--- a/backends/keymapper/keymap.cpp
+++ b/backends/keymapper/keymap.cpp
@@ -22,8 +22,6 @@
 
 #include "backends/keymapper/keymap.h"
 
-#ifdef ENABLE_KEYMAPPER
-
 #include "common/system.h"
 #include "common/tokenizer.h"
 
@@ -247,5 +245,3 @@ bool Keymap::areMappingsIdentical(const Array<const HardwareInput *> &inputs, co
 }
 
 } // End of namespace Common
-
-#endif // #ifdef ENABLE_KEYMAPPER
diff --git a/backends/keymapper/keymap.h b/backends/keymapper/keymap.h
index 1cebd338..dae35f1 100644
--- a/backends/keymapper/keymap.h
+++ b/backends/keymapper/keymap.h
@@ -25,8 +25,6 @@
 
 #include "common/scummsys.h"
 
-#ifdef ENABLE_KEYMAPPER
-
 #include "common/config-manager.h"
 #include "common/func.h"
 #include "common/hashmap.h"
@@ -152,6 +150,4 @@ private:
 
 } // End of namespace Common
 
-#endif // #ifdef ENABLE_KEYMAPPER
-
 #endif // #ifndef COMMON_KEYMAP_H
diff --git a/backends/keymapper/keymapper-defaults.h b/backends/keymapper/keymapper-defaults.h
index 11a0e58..b6d395e 100644
--- a/backends/keymapper/keymapper-defaults.h
+++ b/backends/keymapper/keymapper-defaults.h
@@ -20,8 +20,6 @@
  *
  */
 
-#ifdef ENABLE_KEYMAPPER
-
 #ifndef KEYMAPPER_DEFAULTS_H
 #define KEYMAPPER_DEFAULTS_H
 
@@ -53,4 +51,3 @@ public:
 } //namespace Common
 
 #endif // #ifndef KEYMAPPER_DEFAULTS_H
-#endif // #ifdef ENABLE_KEYMAPPER
diff --git a/backends/keymapper/keymapper.cpp b/backends/keymapper/keymapper.cpp
index d7c0869..846a592 100644
--- a/backends/keymapper/keymapper.cpp
+++ b/backends/keymapper/keymapper.cpp
@@ -22,8 +22,6 @@
 
 #include "backends/keymapper/keymapper.h"
 
-#ifdef ENABLE_KEYMAPPER
-
 #include "backends/keymapper/action.h"
 #include "backends/keymapper/hardware-input.h"
 
@@ -257,5 +255,3 @@ const HardwareInput *Keymapper::findHardwareInput(const Event &event) {
 }
 
 } // End of namespace Common
-
-#endif // #ifdef ENABLE_KEYMAPPER
diff --git a/backends/keymapper/keymapper.h b/backends/keymapper/keymapper.h
index 3c89ce7..10310a8 100644
--- a/backends/keymapper/keymapper.h
+++ b/backends/keymapper/keymapper.h
@@ -25,8 +25,6 @@
 
 #include "common/scummsys.h"
 
-#ifdef ENABLE_KEYMAPPER
-
 #include "backends/keymapper/keymap.h"
 
 #include "common/array.h"
@@ -152,6 +150,4 @@ private:
 
 } // End of namespace Common
 
-#endif // #ifdef ENABLE_KEYMAPPER
-
 #endif // #ifndef COMMON_KEYMAPPER_H
diff --git a/backends/keymapper/remap-widget.cpp b/backends/keymapper/remap-widget.cpp
index bf58463..35ce5ad 100644
--- a/backends/keymapper/remap-widget.cpp
+++ b/backends/keymapper/remap-widget.cpp
@@ -22,8 +22,6 @@
 
 #include "backends/keymapper/remap-widget.h"
 
-#ifdef ENABLE_KEYMAPPER
-
 #include "backends/keymapper/action.h"
 #include "backends/keymapper/hardware-input.h"
 #include "backends/keymapper/input-watcher.h"
@@ -307,5 +305,3 @@ GUI::Widget *RemapWidget::findWidget(int x, int y) {
 }
 
 } // End of namespace Common
-
-#endif // #ifdef ENABLE_KEYMAPPER
diff --git a/backends/keymapper/remap-widget.h b/backends/keymapper/remap-widget.h
index a2bc012..4fe97cf 100644
--- a/backends/keymapper/remap-widget.h
+++ b/backends/keymapper/remap-widget.h
@@ -24,9 +24,6 @@
 #define REMAP_WIDGET_H
 
 #include "common/scummsys.h"
-
-#ifdef ENABLE_KEYMAPPER
-
 #include "common/hash-ptr.h"
 
 #include "gui/widget.h"
@@ -101,6 +98,4 @@ protected:
 
 } // End of namespace Common
 
-#endif // #ifdef ENABLE_KEYMAPPER
-
 #endif // #ifndef REMAP_WIDGET_H
diff --git a/backends/module.mk b/backends/module.mk
index db01661..f62c1e2 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -8,6 +8,12 @@ MODULE_OBJS := \
 	events/default/default-events.o \
 	fs/abstract-fs.o \
 	fs/stdiostream.o \
+	keymapper/action.o \
+	keymapper/hardware-input.o \
+	keymapper/input-watcher.o \
+	keymapper/keymap.o \
+	keymapper/keymapper.o \
+	keymapper/remap-widget.o \
 	log/log.o \
 	midi/alsa.o \
 	midi/dmedia.o \
@@ -101,16 +107,6 @@ MODULE_OBJS += \
 	plugins/elf/version.o
 endif
 
-ifdef ENABLE_KEYMAPPER
-MODULE_OBJS += \
-	keymapper/action.o \
-	keymapper/hardware-input.o \
-	keymapper/input-watcher.o \
-	keymapper/keymap.o \
-	keymapper/keymapper.o \
-	keymapper/remap-widget.o
-endif
-
 ifdef ENABLE_VKEYBD
 MODULE_OBJS += \
 	vkeybd/image-map.o \
diff --git a/backends/platform/androidsdl/androidsdl-sdl.h b/backends/platform/androidsdl/androidsdl-sdl.h
index e83f610..531a7ce 100644
--- a/backends/platform/androidsdl/androidsdl-sdl.h
+++ b/backends/platform/androidsdl/androidsdl-sdl.h
@@ -36,11 +36,6 @@ public:
 	void switchToDirectMouseMode();
 	void switchToRelativeMouseMode();
 	void showOnScreenControl(bool enable);
-
-#ifdef ENABLE_KEYMAPPER
-	// FIXME: This just calls parent methods, is it needed?
-	virtual Common::HardwareInputSet *getHardwareInputSet();
-#endif
 };
 
 #endif
diff --git a/backends/platform/linuxmoto/hardwarekeys.cpp b/backends/platform/linuxmoto/hardwarekeys.cpp
index 70e55c8..5d18aee 100644
--- a/backends/platform/linuxmoto/hardwarekeys.cpp
+++ b/backends/platform/linuxmoto/hardwarekeys.cpp
@@ -24,8 +24,6 @@
 #include "backends/keymapper/keymapper.h"
 #include "common/keyboard.h"
 
-#ifdef ENABLE_KEYMAPPER
-
 using namespace Common;
 
 struct Key {
@@ -109,4 +107,3 @@ static const Mod modifiers[] = {
 Common::HardwareInputSet *OSystem_LINUXMOTO::getHardwareInputSet() {
 	return OSystem_SDL::getHardwareInputSet();
 }
-#endif
diff --git a/backends/platform/linuxmoto/linuxmoto-sdl.h b/backends/platform/linuxmoto/linuxmoto-sdl.h
index b0bf7b4..186bac0 100644
--- a/backends/platform/linuxmoto/linuxmoto-sdl.h
+++ b/backends/platform/linuxmoto/linuxmoto-sdl.h
@@ -28,11 +28,6 @@
 class OSystem_LINUXMOTO : public OSystem_POSIX {
 public:
 	virtual void initBackend();
-
-#ifdef ENABLE_KEYMAPPER
-	// FIXME: This just calls parent methods, is it needed?
-	virtual Common::HardwareInputSet *getHardwareInputSet();
-#endif
 };
 
 #endif
diff --git a/backends/platform/maemo/maemo.cpp b/backends/platform/maemo/maemo.cpp
index 60a940c..21e7c75 100644
--- a/backends/platform/maemo/maemo.cpp
+++ b/backends/platform/maemo/maemo.cpp
@@ -45,12 +45,9 @@ OSystem_SDL_Maemo::OSystem_SDL_Maemo()
 
 OSystem_SDL_Maemo::~OSystem_SDL_Maemo() {
 	delete _eventObserver;
-#ifdef ENABLE_KEYMAPPER
 	delete _keymapperDefaultBindings;
-#endif
 }
 
-#ifdef ENABLE_KEYMAPPER
 static void registerDefaultKeyBindings(Common::KeymapperDefaultBindings *_keymapperDefaultBindings, Model _model) {
 	_keymapperDefaultBindings->setDefaultBinding("gui", "REMP", "HOME");
 	_keymapperDefaultBindings->setDefaultBinding("global", "REMP", "HOME");
@@ -78,7 +75,6 @@ static void registerDefaultKeyBindings(Common::KeymapperDefaultBindings *_keymap
 	_keymapperDefaultBindings->setDefaultBinding("maemo", "RCLK", "ZOOMPLUS");
 	_keymapperDefaultBindings->setDefaultBinding("maemo", "CLKM", "ZOOMMINUS");
 }
-#endif
 
 void OSystem_SDL_Maemo::init() {
 	// Use an iconless window for Maemo
@@ -103,16 +99,12 @@ void OSystem_SDL_Maemo::initBackend() {
 	if (_eventObserver == 0)
 		_eventObserver = new MaemoSdlEventObserver((MaemoSdlEventSource *)_eventSource);
 
-#ifdef ENABLE_KEYMAPPER
 	if (_keymapperDefaultBindings == 0)
 		_keymapperDefaultBindings = new Common::KeymapperDefaultBindings();
-#endif
 
 	_model = detectModel();
 
-#ifdef ENABLE_KEYMAPPER
 	registerDefaultKeyBindings(_keymapperDefaultBindings, _model);
-#endif
 
 	// Call parent implementation of this method
 	OSystem_POSIX::initBackend();
@@ -180,7 +172,6 @@ const Maemo::Model OSystem_SDL_Maemo::detectModel() {
 	return *model;
 }
 
-#ifdef ENABLE_KEYMAPPER
 static const Common::KeyTableEntry maemoKeys[] = {
 	// Function keys
 	{"MENU", Common::KEYCODE_F11, "Menu"},
@@ -223,7 +214,6 @@ Common::Keymap *OSystem_SDL_Maemo::getGlobalKeymap() {
 
 	return globalMap;
 }
-#endif
 
 void OSystem_SDL_Maemo::initObserver() {
 	assert(_eventManager);
diff --git a/backends/platform/maemo/maemo.h b/backends/platform/maemo/maemo.h
index 6d6e09b..3a26cc7 100644
--- a/backends/platform/maemo/maemo.h
+++ b/backends/platform/maemo/maemo.h
@@ -41,11 +41,9 @@ public:
 	virtual void quit();
 	virtual void fatalError();
 	virtual void setWindowCaption(const char *caption);
-#ifdef ENABLE_KEYMAPPER
 	virtual Common::HardwareInputSet *getHardwareInputSet();
 	virtual Common::Keymap *getGlobalKeymap();
 	virtual Common::KeymapperDefaultBindings *getKeymapperDefaultBindings() { return _keymapperDefaultBindings; }
-#endif
 
 	Model getModel() { return _model; }
 
@@ -56,9 +54,7 @@ private:
 	const Model detectModel();
 	Model _model;
 	MaemoSdlEventObserver *_eventObserver;
-#ifdef ENABLE_KEYMAPPER
 	Common::KeymapperDefaultBindings *_keymapperDefaultBindings;
-#endif
 };
 
 } // namespace Maemo
diff --git a/backends/platform/symbian/src/portdefs.h b/backends/platform/symbian/src/portdefs.h
index 598dfab..1a93c9c 100644
--- a/backends/platform/symbian/src/portdefs.h
+++ b/backends/platform/symbian/src/portdefs.h
@@ -171,9 +171,6 @@ namespace std
 #define USE_ARM_COSTUME_ASM
 #define USE_ARM_SOUND_ASM
 #endif
-// This is not really functioning yet.
-// Default SDL keys should map to standard keys I think!
-//#define ENABLE_KEYMAPPER
 
 // Symbian bsearch implementation is flawed
 void *scumm_bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
diff --git a/base/main.cpp b/base/main.cpp
index fbfb456..f78af62 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -281,14 +281,12 @@ static Common::Error runGame(const Plugin *plugin, OSystem &system, const Common
 	}
 #endif // USE_TRANSLATION
 
-#ifdef ENABLE_KEYMAPPER
 	// Initialize any game-specific keymaps
 	Common::Keymap *gameKeymap = metaEngine.initKeymap(target.c_str());
 	Common::Keymapper *keymapper = system.getEventManager()->getKeymapper();
 	if (gameKeymap) {
 		keymapper->addGameKeymap(gameKeymap);
 	}
-#endif
 
 	// Inform backend that the engine is about to be run
 	system.engineInit();
@@ -300,9 +298,7 @@ static Common::Error runGame(const Plugin *plugin, OSystem &system, const Common
 	system.engineDone();
 
 	// Clean up any game-specific keymaps
-#ifdef ENABLE_KEYMAPPER
 	keymapper->cleanupGameKeymaps();
-#endif
 
 	// Free up memory
 	delete engine;
@@ -359,7 +355,6 @@ static void setupGraphics(OSystem &system) {
 }
 
 static void setupKeymapper(OSystem &system) {
-#ifdef ENABLE_KEYMAPPER
 	using namespace Common;
 
 	Keymapper *mapper = system.getEventManager()->getKeymapper();
@@ -382,8 +377,6 @@ static void setupKeymapper(OSystem &system) {
 		String platformGlobalKeymapName = platformGlobalKeymap->getName();
 		mapper->addGlobalKeymap(platformGlobalKeymap);
 	}
-#endif
-
 }
 
 extern "C" int scummvm_main(int argc, const char * const argv[]) {
diff --git a/base/version.cpp b/base/version.cpp
index 75a8870..998ebc5 100644
--- a/base/version.cpp
+++ b/base/version.cpp
@@ -151,10 +151,6 @@ const char *gScummVMFeatures = ""
 	"PNG "
 #endif
 
-#ifdef ENABLE_KEYMAPPER
-	"keymapper "
-#endif
-
 #ifdef ENABLE_VKEYBD
 	"virtual keyboard "
 #endif
diff --git a/common/EventMapper.cpp b/common/EventMapper.cpp
index 6cb5e52..a97da7e 100644
--- a/common/EventMapper.cpp
+++ b/common/EventMapper.cpp
@@ -75,13 +75,11 @@ List<Event> DefaultEventMapper::mapEvent(const Event &ev) {
 	if (mappedEvent.type == EVENT_INVALID)
 		mappedEvent = ev;
 
-#ifdef ENABLE_KEYMAPPER
 	// 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;
diff --git a/common/config-manager.cpp b/common/config-manager.cpp
index e3f0831..40c9745 100644
--- a/common/config-manager.cpp
+++ b/common/config-manager.cpp
@@ -41,9 +41,7 @@ DECLARE_SINGLETON(ConfigManager);
 char const *const ConfigManager::kApplicationDomain = "scummvm";
 char const *const ConfigManager::kTransientDomain = "__TRANSIENT";
 
-#ifdef ENABLE_KEYMAPPER
 char const *const ConfigManager::kKeymapperDomain = "keymapper";
-#endif
 
 #ifdef USE_CLOUD
 char const *const ConfigManager::kCloudDomain = "cloud";
@@ -68,9 +66,7 @@ void ConfigManager::copyFrom(ConfigManager &source) {
 	_miscDomains = source._miscDomains;
 	_appDomain = source._appDomain;
 	_defaultsDomain = source._defaultsDomain;
-#ifdef ENABLE_KEYMAPPER
 	_keymapperDomain = source._keymapperDomain;
-#endif
 #ifdef USE_CLOUD
 	_cloudDomain = source._cloudDomain;
 #endif
@@ -124,10 +120,8 @@ void ConfigManager::addDomain(const String &domainName, const ConfigManager::Dom
 		return;
 	if (domainName == kApplicationDomain) {
 		_appDomain = domain;
-#ifdef ENABLE_KEYMAPPER
 	} else if (domainName == kKeymapperDomain) {
 		_keymapperDomain = domain;
-#endif
 #ifdef USE_CLOUD
 	} else if (domainName == kCloudDomain) {
 		_cloudDomain = domain;
@@ -168,9 +162,7 @@ void ConfigManager::loadFromStream(SeekableReadStream &stream) {
 	_transientDomain.clear();
 	_domainSaveOrder.clear();
 
-#ifdef ENABLE_KEYMAPPER
 	_keymapperDomain.clear();
-#endif
 #ifdef USE_CLOUD
 	_cloudDomain.clear();
 #endif
@@ -282,10 +274,8 @@ void ConfigManager::flushToDisk() {
 	// Write the application domain
 	writeDomain(*stream, kApplicationDomain, _appDomain);
 
-#ifdef ENABLE_KEYMAPPER
 	// Write the keymapper domain
 	writeDomain(*stream, kKeymapperDomain, _keymapperDomain);
-#endif
 #ifdef USE_CLOUD
 	// Write the cloud domain
 	writeDomain(*stream, kCloudDomain, _cloudDomain);
@@ -373,10 +363,8 @@ const ConfigManager::Domain *ConfigManager::getDomain(const String &domName) con
 		return &_transientDomain;
 	if (domName == kApplicationDomain)
 		return &_appDomain;
-#ifdef ENABLE_KEYMAPPER
 	if (domName == kKeymapperDomain)
 		return &_keymapperDomain;
-#endif
 #ifdef USE_CLOUD
 	if (domName == kCloudDomain)
 		return &_cloudDomain;
@@ -397,10 +385,8 @@ ConfigManager::Domain *ConfigManager::getDomain(const String &domName) {
 		return &_transientDomain;
 	if (domName == kApplicationDomain)
 		return &_appDomain;
-#ifdef ENABLE_KEYMAPPER
 	if (domName == kKeymapperDomain)
 		return &_keymapperDomain;
-#endif
 #ifdef USE_CLOUD
 	if (domName == kCloudDomain)
 		return &_cloudDomain;
diff --git a/common/config-manager.h b/common/config-manager.h
index 58f4373..06e8ea3 100644
--- a/common/config-manager.h
+++ b/common/config-manager.h
@@ -89,10 +89,8 @@ public:
 	/** The transient (pseudo) domain. */
 	static char const *const kTransientDomain;
 
-#ifdef ENABLE_KEYMAPPER
 	/** The name of keymapper domain used to store the key maps */
 	static char const *const kKeymapperDomain;
-#endif
 
 #ifdef USE_CLOUD
 	/** The name of cloud domain used to store user's tokens */
@@ -189,9 +187,7 @@ private:
 	Domain			_appDomain;
 	Domain			_defaultsDomain;
 
-#ifdef ENABLE_KEYMAPPER
 	Domain			_keymapperDomain;
-#endif
 
 #ifdef USE_CLOUD
 	Domain			_cloudDomain;
diff --git a/common/events.h b/common/events.h
index b392b6e..92566ad 100644
--- a/common/events.h
+++ b/common/events.h
@@ -74,13 +74,10 @@ enum EventType {
 	 **/
 	EVENT_PREDICTIVE_DIALOG = 12,
 
-#ifdef ENABLE_KEYMAPPER
-	// 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_START = 18,
 	EVENT_CUSTOM_BACKEND_ACTION_END = 19,
 	EVENT_CUSTOM_BACKEND_HARDWARE = 21,
-#endif
+
 #ifdef ENABLE_VKEYBD
 	EVENT_VIRTUAL_KEYBOARD = 20,
 #endif
@@ -169,11 +166,7 @@ struct Event {
 	 */
 	Point mouse;
 
-#ifdef ENABLE_KEYMAPPER
-	// IMPORTANT NOTE: This is part of the WIP Keymapper. If you plan to use
-	// this, please talk to tsoliman and/or LordHoto.
 	CustomEventType customType;
-#endif
 
 	/* The path of the file or directory dragged to the ScummVM window */
 	Common::String path;
@@ -184,10 +177,7 @@ struct Event {
 	 */
 	JoystickState joystick;
 
-	Event() : type(EVENT_INVALID), kbdRepeat(false) {
-#ifdef ENABLE_KEYMAPPER
-		customType = 0;
-#endif
+	Event() : type(EVENT_INVALID), kbdRepeat(false), customType(0) {
 	}
 };
 
@@ -502,10 +492,9 @@ public:
 
 	// TODO: Consider removing OSystem::getScreenChangeID and
 	// replacing it by a generic getScreenChangeID method here
-#ifdef ENABLE_KEYMAPPER
+
 	virtual Keymapper *getKeymapper() = 0;
 	virtual Keymap *getGlobalKeymap() = 0;
-#endif
 
 	enum {
 		/**
diff --git a/common/system.h b/common/system.h
index 2556795..24c1987 100644
--- a/common/system.h
+++ b/common/system.h
@@ -58,11 +58,9 @@ class DialogManager;
 class TimerManager;
 class SeekableReadStream;
 class WriteStream;
-#ifdef ENABLE_KEYMAPPER
 class HardwareInputSet;
 class Keymap;
 class KeymapperDefaultBindings;
-#endif
 class Encoding;
 }
 
@@ -1139,11 +1137,8 @@ public:
 		return _eventManager;
 	}
 
-#ifdef ENABLE_KEYMAPPER
 	/**
 	 * Register hardware inputs with keymapper
-	 * IMPORTANT NOTE: This is part of the WIP Keymapper. If you plan to use
-	 * this, please talk to tsoliman and/or LordHoto.
 	 *
 	 * @return HardwareInputSet with all keys and recommended mappings
 	 *
@@ -1153,8 +1148,6 @@ public:
 
 	/**
 	 * Return a platform-specific global keymap
-	 * IMPORTANT NOTE: This is part of the WIP Keymapper. If you plan to use
-	 * this, please talk to tsoliman and/or LordHoto.
 	 *
 	 * @return Keymap with actions appropriate for the platform
 	 *
@@ -1166,15 +1159,12 @@ public:
 
 	/**
 	 * Return platform-specific default keybindings
-	 * IMPORTANT NOTE: This is part of the WIP Keymapper. If you plan to use
-	 * this, please talk to tsoliman and/or LordHoto.
 	 *
 	 * @return KeymapperDefaultBindings populated with keybindings
 	 *
 	 * See keymapper documentation for further reference.
 	 */
 	virtual Common::KeymapperDefaultBindings *getKeymapperDefaultBindings() { return nullptr; }
-#endif
 	//@}
 
 
diff --git a/configure b/configure
index 969fb6f..f4f4a49 100755
--- a/configure
+++ b/configure
@@ -186,9 +186,8 @@ _no_pragma_pack=no
 _bink=yes
 _cloud=auto
 _pandoc=no
-# Default vkeybd/keymapper/eventrec options
+# Default vkeybd/eventrec options
 _vkeybd=no
-_keymapper=no
 _eventrec=auto
 # GUI translation options
 _translation=yes
@@ -1045,7 +1044,6 @@ Optional Features:
   --disable-cloud          don't build cloud support
   --disable-system-dialogs don't build support for system dialogs
   --enable-vkeybd          build virtual keyboard support
-  --enable-keymapper       build key mapper support
   --enable-eventrecorder   enable event recording functionality
   --disable-eventrecorder  disable event recording functionality
   --enable-updates         build support for updates
@@ -1277,8 +1275,6 @@ for ac_option in $@; do
 	--disable-translation)       _translation=no         ;;
 	--enable-vkeybd)             _vkeybd=yes             ;;
 	--disable-vkeybd)            _vkeybd=no              ;;
-	--enable-keymapper)          _keymapper=yes          ;;
-	--disable-keymapper)         _keymapper=no           ;;
 	--enable-eventrecorder)      _eventrec=yes           ;;
 	--disable-eventrecorder)     _eventrec=no            ;;
 	--enable-text-console)       _text_console=yes       ;;
@@ -3119,7 +3115,6 @@ if test -n "$_host"; then
 			_libcurl=no
 			_vkeybd=yes
 			_build_hq_scalers=no
-			_keymapper=no
 			# Force disable vorbis on dingux, it has terrible performance compared to tremor
 			_vorbis=no
 			# Force disable seq on dingux, no way to use it and it would get enabled by default with configure
@@ -3222,7 +3217,6 @@ if test -n "$_host"; then
 			_build_scalers=yes
 			_optimization_level=-O3
 			_vkeybd=yes
-			_keymapper=yes
 			_vorbis=no
 			_sdlconfig=sdl-config
 			_port_mk="backends/platform/dingux/dingux.mk"
@@ -3284,7 +3278,6 @@ if test -n "$_host"; then
 
 			_backend="maemo"
 			_vkeybd=yes
-			_keymapper=yes
 			_build_hq_scalers=no
 			_mt32emu=no
 			_alsa=no
@@ -3342,7 +3335,6 @@ if test -n "$_host"; then
 			_build_scalers=no
 			_savegame_timestamp=no
 			_translation=no
-			_keymapper=no
 			_text_console=no
 			_vkeybd=yes
 			_dynamic_modules=no
@@ -3497,7 +3489,6 @@ if test -n "$_host"; then
 			_mt32emu=no
 			_seq_midi=no
 			_vkeybd=no
-			_keymapper=yes
 			add_line_to_config_mk "HOST_COMPILER = `uname`"
 			;;
 		wii)
@@ -5420,22 +5411,11 @@ if test "$_pandocext" = "default"; then
 fi
 
 #
-# Enable vkeybd / keymapper / event recorder
+# Enable vkeybd / event recorder
 #
 define_in_config_if_yes $_vkeybd 'ENABLE_VKEYBD'
-define_in_config_if_yes $_keymapper 'ENABLE_KEYMAPPER'
 define_in_config_if_yes $_eventrec 'ENABLE_EVENTRECORDER'
 
-#
-# Check if the keymapper and the event recorder are enabled simultaneously
-#
-if test "$_keymapper" = yes ; then
-	if test "$_eventrec" = yes ; then
-		echo "ERROR: The keymapper and the event recorder cannot be enabled simultaneously currently, please disable one of the two"
-		exit 1
-	fi
-fi
-
 # Check whether to build translation support
 #
 echo_n "Building translation support... "
@@ -5677,10 +5657,6 @@ if test "$_vkeybd" = yes ; then
 	echo_n ", virtual keyboard"
 fi
 
-if test "$_keymapper" = yes ; then
-	echo_n ", keymapper"
-fi
-
 if test "$_eventrec" = yes ; then
 	echo_n ", event recorder"
 fi
diff --git a/devtools/create_project/create_project.cpp b/devtools/create_project/create_project.cpp
index 7bcea8e..a6324b3 100644
--- a/devtools/create_project/create_project.cpp
+++ b/devtools/create_project/create_project.cpp
@@ -341,17 +341,6 @@ int main(int argc, char *argv[]) {
 			cout << "    " << i->description << '\n';
 	}
 
-	// Check if the keymapper and the event recorder are enabled simultaneously
-	bool keymapperEnabled = false;
-	for (FeatureList::const_iterator i = setup.features.begin(); i != setup.features.end(); ++i) {
-		if (i->enable && !strcmp(i->name, "keymapper"))
-			keymapperEnabled = true;
-		if (i->enable && !strcmp(i->name, "eventrecorder") && keymapperEnabled) {
-			std::cerr << "ERROR: The keymapper and the event recorder cannot be enabled simultaneously currently, please disable one of the two\n";
-			return -1;
-		}
-	}
-
 	// Check if tools and tests are enabled simultaneously
 	if (setup.devTools && setup.tests) {
 		std::cerr << "ERROR: The tools and tests projects cannot be created simultaneously\n";
@@ -1087,7 +1076,6 @@ const Feature s_features[] = {
 	{           "cloud",                     "USE_CLOUD",  "", true,  "Cloud integration support" },
 	{     "translation",               "USE_TRANSLATION",  "", true,  "Translation support" },
 	{          "vkeybd",                 "ENABLE_VKEYBD",  "", false, "Virtual keyboard support"},
-	{       "keymapper",              "ENABLE_KEYMAPPER",  "", false, "Keymapper support"},
 	{   "eventrecorder",          "ENABLE_EVENTRECORDER",  "", false, "Event recorder support"},
 	{         "updates",                   "USE_UPDATES",  "", false, "Updates support"},
 	{         "dialogs",                "USE_SYSDIALOGS",  "", true,  "System dialogs support"},
diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
index f010987..7361b0e 100644
--- a/engines/kyra/engine/eobcommon.cpp
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -344,7 +344,6 @@ EoBCoreEngine::~EoBCoreEngine() {
 }
 
 Common::Keymap *EoBCoreEngine::initKeymap(const Common::String &gameId) {
-#ifdef ENABLE_KEYMAPPER
 	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, kKeymapName);
 
 	const Common::KeyActionEntry keyActionEntries[] = {
@@ -382,9 +381,6 @@ Common::Keymap *EoBCoreEngine::initKeymap(const Common::String &gameId) {
 	}
 
 	return engineKeyMap;
-#else
-	return nullptr;
-#endif
 }
 
 Common::Error EoBCoreEngine::init() {
diff --git a/engines/kyra/engine/lol.cpp b/engines/kyra/engine/lol.cpp
index 64e17c7..4503c0b 100644
--- a/engines/kyra/engine/lol.cpp
+++ b/engines/kyra/engine/lol.cpp
@@ -462,7 +462,6 @@ Common::Error LoLEngine::init() {
 }
 
 Common::Keymap *LoLEngine::initKeymap() {
-#ifdef ENABLE_KEYMAPPER
 	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, kKeymapName);
 
 	const Common::KeyActionEntry keyActionEntries[] = {
@@ -489,9 +488,6 @@ Common::Keymap *LoLEngine::initKeymap() {
 	}
 
 	return engineKeyMap;
-#else
-	return nullptr;
-#endif
 }
 
 void LoLEngine::pauseEngineIntern(bool pause) {
diff --git a/engines/kyra/gui/gui_eob.cpp b/engines/kyra/gui/gui_eob.cpp
index 943dfee..11000c0 100644
--- a/engines/kyra/gui/gui_eob.cpp
+++ b/engines/kyra/gui/gui_eob.cpp
@@ -2580,12 +2580,10 @@ void GUI_EoB::updateBoxFrameHighLight(int box) {
 }
 
 int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColor1, int textColor2, int cursorColor) {
-#ifdef ENABLE_KEYMAPPER
 	// Disable the keymap during text input
 	Common::Keymapper *const mapper = _vm->_eventMan->getKeymapper();
 	Common::Keymap *const lolKeymap = mapper->getKeymap(EoBCoreEngine::kKeymapName);
 	lolKeymap->setEnabled(false);
-#endif
 
 	uint8 cursorState = 1;
 	char sufx[3] = " \0";
@@ -2761,9 +2759,7 @@ int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColo
 
 	} while (_keyPressed.keycode != Common::KEYCODE_RETURN && _keyPressed.keycode != Common::KEYCODE_ESCAPE && !_vm->shouldQuit());
 
-#ifdef ENABLE_KEYMAPPER
 	lolKeymap->setEnabled(true);
-#endif
 
 	return _keyPressed.keycode == Common::KEYCODE_ESCAPE ? -1 : len;
 }
diff --git a/engines/kyra/gui/gui_lol.cpp b/engines/kyra/gui/gui_lol.cpp
index 84e3aa6..c1d5752 100644
--- a/engines/kyra/gui/gui_lol.cpp
+++ b/engines/kyra/gui/gui_lol.cpp
@@ -2559,12 +2559,10 @@ int GUI_LoL::getInput() {
 	if (!_displayMenu)
 		return 0;
 
-#ifdef ENABLE_KEYMAPPER
 	// Disable the keymap during text input
 	Common::Keymapper *const mapper = _vm->_eventMan->getKeymapper();
 	Common::Keymap *const lolKeymap = mapper->getKeymap(LoLEngine::kKeymapName);
 	lolKeymap->setEnabled(false);
-#endif
 
 	Common::Point p = _vm->getMousePos();
 	_vm->_mouseX = p.x;
@@ -2603,9 +2601,7 @@ int GUI_LoL::getInput() {
 
 	_vm->delay(8);
 
-#ifdef ENABLE_KEYMAPPER
 	lolKeymap->setEnabled(true);
-#endif
 
 	return inputFlag & 0x8000 ? 1 : 0;
 }
diff --git a/engines/metaengine.cpp b/engines/metaengine.cpp
index 5d120b4..561cda4 100644
--- a/engines/metaengine.cpp
+++ b/engines/metaengine.cpp
@@ -48,7 +48,6 @@ const char *MetaEngine::getSavegamePattern(const char *target) const {
 }
 
 Common::Keymap *MetaEngine::initKeymap(const char *target) const {
-#ifdef ENABLE_KEYMAPPER
 	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, "engine-default");
 
 	// Since the game has multiple built-in keys for each of these anyway,
@@ -67,9 +66,6 @@ Common::Keymap *MetaEngine::initKeymap(const char *target) const {
 	}
 
 	return engineKeyMap;
-#else
-	return nullptr;
-#endif
 }
 
 void MetaEngine::appendExtendedSave(Common::OutSaveFile *saveFile, uint32 playtime, Common::String desc) {
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index 9ac9783..5c436bf 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -875,7 +875,6 @@ void MohawkEngine_Riven::runOptionsDialog() {
 }
 
 Common::Keymap *MohawkEngine_Riven::initKeymap(const char *target) {
-#ifdef ENABLE_KEYMAPPER
 	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, "riven");
 
 	const Common::KeyActionEntry keyActionEntries[] = {
@@ -925,9 +924,6 @@ Common::Keymap *MohawkEngine_Riven::initKeymap(const char *target) {
 	}
 
 	return engineKeyMap;
-#else
-	return nullptr;
-#endif
 }
 
 bool ZipMode::operator== (const ZipMode &z) const {
diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp
index 9fdb5da..826c892 100644
--- a/engines/pegasus/pegasus.cpp
+++ b/engines/pegasus/pegasus.cpp
@@ -2490,7 +2490,6 @@ uint PegasusEngine::getNeighborhoodCD(const NeighborhoodID neighborhood) const {
 }
 
 Common::Keymap *PegasusEngine::initKeymap() {
-#ifdef ENABLE_KEYMAPPER
 	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, "pegasus");
 
 	// Since the game has multiple built-in keys for each of these anyway,
@@ -2517,9 +2516,6 @@ Common::Keymap *PegasusEngine::initKeymap() {
 	}
 
 	return engineKeyMap;
-#else
-	return nullptr;
-#endif
 }
 
 } // End of namespace Pegasus
diff --git a/gui/editgamedialog.cpp b/gui/editgamedialog.cpp
index 0ef3fa0..cdabb4e 100644
--- a/gui/editgamedialog.cpp
+++ b/gui/editgamedialog.cpp
@@ -200,7 +200,6 @@ EditGameDialog::EditGameDialog(const String &domain)
 	//
 	// The Keymap tab
 	//
-#ifdef ENABLE_KEYMAPPER
 	Common::Keymap *keymap = nullptr;
 	if (plugin) {
 		keymap = plugin->get<MetaEngine>().initKeymap(domain.c_str());
@@ -217,7 +216,6 @@ EditGameDialog::EditGameDialog(const String &domain)
 		tab->addTab(_("Keymaps"), "GameOptions_KeyMapper");
 		addKeyMapperControls(tab, "GameOptions_KeyMapper.", keymaps);
 	}
-#endif
 
 	//
 	// 4) The audio tab
diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp
index 9549041..0f15023 100644
--- a/gui/gui-manager.cpp
+++ b/gui/gui-manager.cpp
@@ -109,8 +109,6 @@ GuiManager::~GuiManager() {
 	delete _theme;
 }
 
-#ifdef ENABLE_KEYMAPPER
-
 Common::Keymap *GuiManager::getKeymap() const {
 	using namespace Common;
 
@@ -144,8 +142,6 @@ void GuiManager::enableKeymap(bool enabled) {
 	keymapper->setEnabledKeymapType(enabled ? Common::Keymap::kKeymapTypeGui : Common::Keymap::kKeymapTypeGame);
 }
 
-#endif
-
 bool GuiManager::loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx, bool forced) {
 	// If we are asked to reload the currently active theme, just do nothing
 	// FIXME: Actually, why? It might be desirable at times to force a theme reload...
@@ -423,10 +419,9 @@ void GuiManager::runLoop() {
 #pragma mark -
 
 void GuiManager::saveState() {
-#ifdef ENABLE_KEYMAPPER
 	initKeymap();
 	enableKeymap(true);
-#endif
+
 	// Backup old cursor
 	_lastClick.x = _lastClick.y = 0;
 	_lastClick.time = 0;
@@ -436,9 +431,8 @@ void GuiManager::saveState() {
 }
 
 void GuiManager::restoreState() {
-#ifdef ENABLE_KEYMAPPER
 	enableKeymap(false);
-#endif
+
 	if (_useStdCursor) {
 		CursorMan.popCursor();
 		CursorMan.popCursorPalette();
diff --git a/gui/options.cpp b/gui/options.cpp
index c81f23f..4eaf074 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -267,12 +267,10 @@ void OptionsDialog::build() {
 		}
 	}
 
-#ifdef ENABLE_KEYMAPPER
 	// Keymapper options
 	if (_keymapperWidget) {
 		_keymapperWidget->build();
 	}
-#endif
 
 	// Graphic options
 	if (_fullscreenCheckbox) {
@@ -630,7 +628,6 @@ void OptionsDialog::apply() {
 		}
 	}
 
-#ifdef ENABLE_KEYMAPPER
 	if (_keymapperWidget) {
 		bool changes = _keymapperWidget->save();
 		if (changes) {
@@ -638,7 +635,6 @@ void OptionsDialog::apply() {
 			keymapper->reloadAllMappings();
 		}
 	}
-#endif
 
 	// Control options
 	if (_enableControlSettings) {
@@ -886,11 +882,9 @@ void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data
 void OptionsDialog::handleTickle() {
 	Dialog::handleTickle();
 
-#ifdef ENABLE_KEYMAPPER
 	if (_keymapperWidget) {
 		_keymapperWidget->handleTickle();
 	}
-#endif
 }
 
 void OptionsDialog::setGraphicSettingsState(bool enabled) {
@@ -1063,11 +1057,9 @@ void OptionsDialog::addControlControls(GuiObject *boss, const Common::String &pr
 	_enableControlSettings = true;
 }
 
-#ifdef ENABLE_KEYMAPPER
 void OptionsDialog::addKeyMapperControls(GuiObject *boss, const Common::String &prefix, const Common::KeymapArray &keymaps) {
 	_keymapperWidget = new Common::RemapWidget(boss, prefix + "Container", keymaps);
 }
-#endif
 
 void OptionsDialog::addShaderControls(GuiObject *boss, const Common::String &prefix) {
 	// Shader selector
@@ -1617,7 +1609,6 @@ void GlobalOptionsDialog::build() {
 	//
 	// The Keymap tab
 	//
-#ifdef ENABLE_KEYMAPPER
 	Common::KeymapArray keymaps;
 
 	Common::Keymap *primaryGlobalKeymap = g_system->getEventManager()->getGlobalKeymap();
@@ -1646,7 +1637,6 @@ void GlobalOptionsDialog::build() {
 		tab->addTab(_("Keymaps"), "GlobalOptions_KeyMapper");
 		addKeyMapperControls(tab, "GlobalOptions_KeyMapper.", keymaps);
 	}
-#endif
 
 	//
 	// 2) The audio tab


Commit: d2f09a4bfc7b758877386fe0431710a2a023bbb1
    https://github.com/scummvm/scummvm/commit/d2f09a4bfc7b758877386fe0431710a2a023bbb1
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
BUILD: Don't build the event recorder by default

It's been broken for a few years, see bug #10045. It's said not to work
with the keymapper which is now always enabled.

Changed paths:
    configure


diff --git a/configure b/configure
index f4f4a49..b286469 100755
--- a/configure
+++ b/configure
@@ -188,7 +188,7 @@ _cloud=auto
 _pandoc=no
 # Default vkeybd/eventrec options
 _vkeybd=no
-_eventrec=auto
+_eventrec=no
 # GUI translation options
 _translation=yes
 # Default platform settings
@@ -3135,7 +3135,6 @@ if test -n "$_host"; then
 			# This is so optional OpenGL ES includes are found.
 			append_var CXXFLAGS "-I$RPI_ROOT/opt/vc/include"
 			_savegame_timestamp=no
-			_eventrec=no
 			_build_scalers=no
 			_build_hq_scalers=no
 			# We prefer SDL2 on the Raspberry Pi: acceleration now depends on it
@@ -3430,7 +3429,6 @@ if test -n "$_host"; then
 		ps3)
 			_timidity=no
 			_vkeybd=yes
-			_eventrec=no
 			_port_mk="backends/platform/sdl/ps3/ps3.mk"
 			;;
 		psp2)
@@ -3440,7 +3438,6 @@ if test -n "$_host"; then
 			_build_hq_scalers=no
 			_mt32emu=no
 			_timidity=no
-			_eventrec=no
 			_port_mk="backends/platform/sdl/psp2/psp2.mk"
 			;;
 		psp)
@@ -3866,9 +3863,6 @@ esac
 #
 case $_backend in
 	sdl)
-		if test "$_eventrec" = auto ; then
-			_eventrec=yes
-		fi
 		;;
 	*)
 		_eventrec=no


Commit: ec9c394787439c84f315e3d82d87ed67a5bd63ff
    https://github.com/scummvm/scummvm/commit/ec9c394787439c84f315e3d82d87ed67a5bd63ff
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
KEYMAPPER: Remove DefaultEventMapper

Now the keymapper is enabled by default, it does not make sense to have
a separate class anymore.

Changed paths:
  R common/EventMapper.cpp
    backends/keymapper/keymapper.cpp
    backends/keymapper/keymapper.h
    common/EventDispatcher.cpp
    common/events.h
    common/module.mk


diff --git a/backends/keymapper/keymapper.cpp b/backends/keymapper/keymapper.cpp
index 846a592..e4b580e 100644
--- a/backends/keymapper/keymapper.cpp
+++ b/backends/keymapper/keymapper.cpp
@@ -33,12 +33,14 @@ namespace Common {
 static const uint32 kDelayKeyboardEventMillis = 250;
 static const uint32 kDelayMouseEventMillis = 50;
 
-Keymapper::Keymapper(EventManager *evtMgr) :
-		_eventMan(evtMgr),
+Keymapper::Keymapper(EventManager *eventMan) :
+		_eventMan(eventMan),
 		_enabled(true),
 		_enabledKeymapType(Keymap::kKeymapTypeGlobal),
 		_hardwareInputs(nullptr),
-		_backendDefaultBindings(nullptr) {
+		_backendDefaultBindings(nullptr),
+		_delayedEventSource(new DelayedEventSource()) {
+	_eventMan->getEventDispatcher()->registerSource(_delayedEventSource, true);
 }
 
 Keymapper::~Keymapper() {
@@ -138,12 +140,18 @@ void Keymapper::setEnabledKeymapType(Keymap::KeymapType type) {
 
 List<Event> Keymapper::mapEvent(const Event &ev) {
 	if (!_enabled) {
-		return DefaultEventMapper::mapEvent(ev);
+		List<Event> originalEvent;
+		originalEvent.push_back(ev);
+		return originalEvent;
 	}
 
+	hardcodedEventMapping(ev);
+
 	const HardwareInput *hwInput = findHardwareInput(ev);
 	if (!hwInput) {
-		return DefaultEventMapper::mapEvent(ev);
+		List<Event> originalEvent;
+		originalEvent.push_back(ev);
+		return originalEvent;
 	}
 
 	IncomingEventType incomingEventType = convertToIncomingEventType(ev);
@@ -173,7 +181,8 @@ List<Event> Keymapper::mapEvent(const Event &ev) {
 	}
 
 	if (mappedEvents.empty()) {
-		return DefaultEventMapper::mapEvent(ev);
+		// if it didn't get mapped, just pass it through
+		mappedEvents.push_back(ev);
 	}
 
 	return mappedEvents;
@@ -205,14 +214,14 @@ Event Keymapper::executeAction(const Action *action, IncomingEventType incomingT
 	if (incomingType == kIncomingEventInstant && 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);
+		_delayedEventSource->scheduleEvent(evt, 0);
 
 		// non-keys need to send up as well
 		// 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);
+		_delayedEventSource->scheduleEvent(evt, delay);
 	}
 
 	return evt;
@@ -254,4 +263,69 @@ const HardwareInput *Keymapper::findHardwareInput(const Event &event) {
 	}
 }
 
+void Keymapper::hardcodedEventMapping(Event ev) {
+	// TODO: Either add support for long presses to the keymapper
+	// or move this elsewhere as an event observer + source
+#ifdef ENABLE_VKEYBD
+	// Trigger virtual keyboard on long press of more than 1 second
+	// of middle mouse button.
+	const uint32 vkeybdTime = 1000;
+
+	static uint32 vkeybdThen = 0;
+
+	if (ev.type == EVENT_MBUTTONDOWN) {
+		vkeybdThen = g_system->getMillis();
+	}
+
+	if (ev.type == EVENT_MBUTTONUP) {
+		if ((g_system->getMillis() - vkeybdThen) >= vkeybdTime) {
+			Event vkeybdEvent;
+			vkeybdEvent.type = EVENT_VIRTUAL_KEYBOARD;
+
+			// Avoid blocking event from engine.
+			_delayedEventSource->scheduleEvent(vkeybdEvent, 100);
+		}
+	}
+#endif
+
+	if (ev.type == EVENT_JOYBUTTON_DOWN) {
+		if (ev.joystick.button == JOYSTICK_BUTTON_START || ev.joystick.button == JOYSTICK_BUTTON_GUIDE) {
+			ev.type = EVENT_MAINMENU;
+		}
+	}
+}
+
+void DelayedEventSource::scheduleEvent(const Event &ev, uint32 delayMillis) {
+	if (_delayedEvents.empty()) {
+		_delayedEffectiveTime = g_system->getMillis() + delayMillis;
+		delayMillis = 0;
+	}
+	DelayedEventsEntry entry = DelayedEventsEntry(delayMillis, ev);
+	_delayedEvents.push(entry);
+}
+
+bool DelayedEventSource::pollEvent(Event &event) {
+	if (_delayedEvents.empty()) {
+		return false;
+	}
+
+	uint32 now = g_system->getMillis();
+
+	if (now >= _delayedEffectiveTime) {
+		event = _delayedEvents.pop().event;
+
+		if (!_delayedEvents.empty()) {
+			_delayedEffectiveTime += _delayedEvents.front().timerOffset;
+		}
+
+		return true;
+	}
+
+	return false;
+}
+
+bool DelayedEventSource::allowMapping() const {
+	return false; // Events from this source have already been mapped, and should not be mapped again
+}
+
 } // End of namespace Common
diff --git a/backends/keymapper/keymapper.h b/backends/keymapper/keymapper.h
index 10310a8..c5ee304 100644
--- a/backends/keymapper/keymapper.h
+++ b/backends/keymapper/keymapper.h
@@ -37,13 +37,14 @@ const char *const kGuiKeymapName = "gui";
 const char *const kGlobalKeymapName = "global";
 
 class Action;
+class DelayedEventSource;
 struct HardwareInput;
 class HardwareInputSet;
 class KeymapperDefaultBindings;
 
 typedef Array<Keymap *> KeymapArray;
 
-class Keymapper : public Common::DefaultEventMapper {
+class Keymapper : public Common::EventMapper {
 public:
 
 	Keymapper(EventManager *eventMan);
@@ -125,6 +126,10 @@ public:
 	void initKeymap(Keymap *keymap, ConfigManager::Domain *domain);
 
 private:
+	EventManager *_eventMan;
+	HardwareInputSet *_hardwareInputs;
+	const KeymapperDefaultBindings *_backendDefaultBindings;
+	DelayedEventSource *_delayedEventSource;
 
 	enum IncomingEventType {
 		kIncomingEventStart,
@@ -132,20 +137,38 @@ private:
 		kIncomingEventInstant
 	};
 
-	HardwareInputSet *_hardwareInputs;
-	const KeymapperDefaultBindings *_backendDefaultBindings;
+	bool _enabled;
+	Keymap::KeymapType _enabledKeymapType;
+
+	KeymapArray _keymaps;
 
 	Event executeAction(const Action *act, IncomingEventType incomingType);
 	EventType convertStartToEnd(EventType eventType);
 	IncomingEventType convertToIncomingEventType(const Event &ev) const;
 
-	EventManager *_eventMan;
+	void hardcodedEventMapping(Event ev);
+};
 
-	bool _enabled;
-	Keymap::KeymapType _enabledKeymapType;
+class DelayedEventSource : public EventSource {
+public:
+	// EventSource API
+	bool pollEvent(Event &event) override;
+	bool allowMapping() const override;
 
-	KeymapArray _keymaps;
+	/**
+	 * Schedule an event to be produced after the specified delay
+	 */
+	void scheduleEvent(const Event &ev, uint32 delayMillis);
+
+private:
+	struct DelayedEventsEntry {
+		const uint32 timerOffset;
+		const Event event;
+		DelayedEventsEntry(const uint32 offset, const Event ev) : timerOffset(offset), event(ev) { }
+	};
 
+	Queue<DelayedEventsEntry> _delayedEvents;
+	uint32 _delayedEffectiveTime;
 };
 
 } // End of namespace Common
diff --git a/common/EventDispatcher.cpp b/common/EventDispatcher.cpp
index f380146..ccfc40f 100644
--- a/common/EventDispatcher.cpp
+++ b/common/EventDispatcher.cpp
@@ -72,12 +72,6 @@ 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::clearEvents() {
diff --git a/common/EventMapper.cpp b/common/EventMapper.cpp
deleted file mode 100644
index a97da7e..0000000
--- a/common/EventMapper.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "common/events.h"
-
-#include "common/system.h"
-#include "common/textconsole.h"
-
-namespace Common {
-
-List<Event> DefaultEventMapper::mapEvent(const Event &ev) {
-	List<Event> events;
-	Event mappedEvent;
-#ifdef ENABLE_VKEYBD
-	// Trigger virtual keyboard on long press of more than 1 second
-	// of middle mouse button.
-	const uint32 vkeybdTime = 1000;
-
-	static uint32 vkeybdThen = 0;
-
-	if (ev.type == EVENT_MBUTTONDOWN) {
-		vkeybdThen = g_system->getMillis();
-	}
-
-	if (ev.type == EVENT_MBUTTONUP) {
-		if ((g_system->getMillis() - vkeybdThen) >= vkeybdTime) {
-			mappedEvent.type = EVENT_VIRTUAL_KEYBOARD;
-
-			// Avoid blocking event from engine.
-			addDelayedEvent(100, ev);
-		}
-	}
-#endif
-
-	if (ev.type == EVENT_KEYDOWN) {
-		if (ev.kbd.hasFlags(KBD_CTRL) && ev.kbd.keycode == KEYCODE_F5) {
-			mappedEvent.type = EVENT_MAINMENU;
-		}
-#ifdef ENABLE_VKEYBD
-		else if (ev.kbd.hasFlags(KBD_CTRL) && ev.kbd.keycode == KEYCODE_F7) {
-			mappedEvent.type = EVENT_VIRTUAL_KEYBOARD;
-
-			// Avoid blocking CTRL-F7 events from engine.
-			addDelayedEvent(100, ev);
-		}
-#endif
-	}
-
-	if (ev.type == EVENT_JOYBUTTON_DOWN) {
-		if (ev.joystick.button == JOYSTICK_BUTTON_START || ev.joystick.button == JOYSTICK_BUTTON_GUIDE) {
-			mappedEvent.type = EVENT_MAINMENU;
-		}
-	}
-
-	// if it didn't get mapped, just pass it through
-	if (mappedEvent.type == EVENT_INVALID)
-		mappedEvent = ev;
-
-	// 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>();
-	}
-
-	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 92566ad..ddb32ca 100644
--- a/common/events.h
+++ b/common/events.h
@@ -283,27 +283,6 @@ public:
 	 * Map an incoming event to one or more action events
 	 */
 	virtual List<Event> mapEvent(const Event &ev) = 0;
-
-	virtual List<Event> getDelayedEvents() = 0;
-};
-
-class DefaultEventMapper : public EventMapper {
-public:
-	DefaultEventMapper() : _delayedEvents(), _delayedEffectiveTime(0) {}
-	// EventMapper interface
-	virtual List<Event> mapEvent(const Event &ev);
-	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/common/module.mk b/common/module.mk
index 2bac6ab..717d37a 100644
--- a/common/module.mk
+++ b/common/module.mk
@@ -8,7 +8,6 @@ MODULE_OBJS := \
 	debug.o \
 	error.o \
 	EventDispatcher.o \
-	EventMapper.o \
 	file.o \
 	fs.o \
 	gui_options.o \


Commit: 7617723ab57458d8b3a326d093e4b9a5ad8cac98
    https://github.com/scummvm/scummvm/commit/7617723ab57458d8b3a326d093e4b9a5ad8cac98
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
KEYMAPPER: Allow backends to register multiple keymaps

Changed paths:
    backends/platform/maemo/maemo.cpp
    backends/platform/maemo/maemo.h
    base/main.cpp
    common/system.h
    gui/options.cpp


diff --git a/backends/platform/maemo/maemo.cpp b/backends/platform/maemo/maemo.cpp
index 21e7c75..38f36cd 100644
--- a/backends/platform/maemo/maemo.cpp
+++ b/backends/platform/maemo/maemo.cpp
@@ -187,8 +187,10 @@ Common::HardwareInputSet *OSystem_SDL_Maemo::getHardwareInputSet() {
 	return new Common::HardwareInputSet(true, maemoKeys);
 }
 
-Common::Keymap *OSystem_SDL_Maemo::getGlobalKeymap() {
+Common::KeymapArray OSystem_SDL_Maemo::getGlobalKeymaps() {
 	using namespace Common;
+	KeymapArray globalMaps = OSystem_POSIX::getGlobalKeymaps();
+
 	Keymap *globalMap = new Keymap(Keymap::kKeymapTypeGlobal, "maemo");
 
 	Action *act;
@@ -212,7 +214,9 @@ Common::Keymap *OSystem_SDL_Maemo::getGlobalKeymap() {
 	act->setRightClickEvent();
 	globalMap->addAction(act);
 
-	return globalMap;
+	globalMaps.push_back(globalMap);
+
+	return globalMaps;
 }
 
 void OSystem_SDL_Maemo::initObserver() {
diff --git a/backends/platform/maemo/maemo.h b/backends/platform/maemo/maemo.h
index 3a26cc7..b565a68 100644
--- a/backends/platform/maemo/maemo.h
+++ b/backends/platform/maemo/maemo.h
@@ -42,7 +42,7 @@ public:
 	virtual void fatalError();
 	virtual void setWindowCaption(const char *caption);
 	virtual Common::HardwareInputSet *getHardwareInputSet();
-	virtual Common::Keymap *getGlobalKeymap();
+	Common::KeymapArray getGlobalKeymaps() override;
 	virtual Common::KeymapperDefaultBindings *getKeymapperDefaultBindings() { return _keymapperDefaultBindings; }
 
 	Model getModel() { return _model; }
diff --git a/base/main.cpp b/base/main.cpp
index f78af62..048640e 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -372,10 +372,9 @@ static void setupKeymapper(OSystem &system) {
 	}
 
 	// Get the platform-specific global keymap (if it exists)
-	Keymap *platformGlobalKeymap = system.getGlobalKeymap();
-	if (platformGlobalKeymap) {
-		String platformGlobalKeymapName = platformGlobalKeymap->getName();
-		mapper->addGlobalKeymap(platformGlobalKeymap);
+	KeymapArray platformKeymaps = system.getGlobalKeymaps();
+	for (uint i = 0; i < platformKeymaps.size(); i++) {
+		mapper->addGlobalKeymap(platformKeymaps[i]);
 	}
 }
 
diff --git a/common/system.h b/common/system.h
index 24c1987..8893747 100644
--- a/common/system.h
+++ b/common/system.h
@@ -25,6 +25,7 @@
 
 #include "common/scummsys.h"
 #include "common/noncopyable.h"
+#include "common/array.h" // For OSystem::getGlobalKeymaps()
 #include "common/list.h" // For OSystem::getSupportedFormats()
 #include "graphics/pixelformat.h"
 #include "graphics/mode.h"
@@ -62,6 +63,8 @@ class HardwareInputSet;
 class Keymap;
 class KeymapperDefaultBindings;
 class Encoding;
+
+typedef Array<Keymap *> KeymapArray;
 }
 
 class AudioCDManager;
@@ -1155,7 +1158,7 @@ public:
 	 *
 	 * See keymapper documentation for further reference.
 	 */
-	virtual Common::Keymap *getGlobalKeymap() { return nullptr; }
+	virtual Common::KeymapArray getGlobalKeymaps() { return Common::KeymapArray(); }
 
 	/**
 	 * Return platform-specific default keybindings
diff --git a/gui/options.cpp b/gui/options.cpp
index 4eaf074..be4ef97 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -1616,10 +1616,7 @@ void GlobalOptionsDialog::build() {
 		keymaps.push_back(primaryGlobalKeymap);
 	}
 
-	Common::Keymap *platformGlobalKeymap = g_system->getGlobalKeymap();
-	if (platformGlobalKeymap && !platformGlobalKeymap->getActions().empty()) {
-		keymaps.push_back(platformGlobalKeymap);
-	}
+	keymaps.push_back(g_system->getGlobalKeymaps());
 
 	Common::Keymap *guiKeymap = g_gui.getKeymap();
 	if (guiKeymap && !guiKeymap->getActions().empty()) {


Commit: c131e8f5b933398e328c30c445020e7bc788261a
    https://github.com/scummvm/scummvm/commit/c131e8f5b933398e328c30c445020e7bc788261a
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
EVENTS: Use the keymapper for some previously hard-coded key bindings

Changed paths:
    backends/events/default/default-events.cpp
    backends/events/sdl/sdl-events.cpp
    engines/metaengine.cpp


diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp
index 2a148bc..6651075 100644
--- a/backends/events/default/default-events.cpp
+++ b/backends/events/default/default-events.cpp
@@ -324,16 +324,30 @@ Common::Keymap *DefaultEventManager::getGlobalKeymap() {
 	act->setKeyEvent(KeyState(KEYCODE_RETURN, ASCII_RETURN, KBD_ALT));
 	globalKeymap->addAction(act);
 
-	act = new Action("LCLK", _("Left Click"));
-	act->setLeftClickEvent();
+	act = new Action("MUTE", _("Toggle mute"));
+	act->addDefaultInputMapping("C+u");
+	act->setEvent(EVENT_MUTE);
 	globalKeymap->addAction(act);
 
-	act = new Action("MCLK", _("Middle Click"));
-	act->setMiddleClickEvent();
-	globalKeymap->addAction(act);
+	act = new Action("QUIT", _("Quit"));
+	act->setEvent(EVENT_QUIT);
+
+#if defined(MACOSX)
+	// On Macintosh, Cmd-Q quits
+	act->addDefaultInputMapping("M+q");
+#elif defined(POSIX)
+	// On other *nix systems, Control-Q quits
+	act->addDefaultInputMapping("C+q");
+#else
+	// Ctrl-z quits
+	act->addDefaultInputMapping("C+z");
+
+#ifdef WIN32
+	// On Windows, also use the default Alt-F4 quit combination
+	act->addDefaultInputMapping("A+F4");
+#endif
+#endif
 
-	act = new Action("RCLK", _("Right Click"));
-	act->setRightClickEvent();
 	globalKeymap->addAction(act);
 
 	return globalKeymap;
diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp
index e8ea55f..e61cadb 100644
--- a/backends/events/sdl/sdl-events.cpp
+++ b/backends/events/sdl/sdl-events.cpp
@@ -761,40 +761,6 @@ bool SdlEventSource::handleKeyDown(SDL_Event &ev, Common::Event &event) {
 		return false;
 	}
 
-#if defined(MACOSX)
-	// On Macintosh, Cmd-Q quits
-	if ((ev.key.keysym.mod & KMOD_META) && sdlKeycode == 'q') {
-		event.type = Common::EVENT_QUIT;
-		return true;
-	}
-#elif defined(POSIX)
-	// On other *nix systems, Control-Q quits
-	if ((ev.key.keysym.mod & KMOD_CTRL) && sdlKeycode == 'q') {
-		event.type = Common::EVENT_QUIT;
-		return true;
-	}
-#else
-	// Ctrl-z quits
-	if ((event.kbd.hasFlags(Common::KBD_CTRL) && sdlKeycode == 'z')) {
-		event.type = Common::EVENT_QUIT;
-		return true;
-	}
-
-	#ifdef WIN32
-	// On Windows, also use the default Alt-F4 quit combination
-	if ((ev.key.keysym.mod & KMOD_ALT) && sdlKeycode == SDLK_F4) {
-		event.type = Common::EVENT_QUIT;
-		return true;
-	}
-	#endif
-#endif
-
-	// Ctrl-u toggles mute
-	if ((ev.key.keysym.mod & KMOD_CTRL) && sdlKeycode == 'u') {
-		event.type = Common::EVENT_MUTE;
-		return true;
-	}
-
 	if (remapKey(ev, event))
 		return true;
 
@@ -821,24 +787,10 @@ bool SdlEventSource::handleKeyUp(SDL_Event &ev, Common::Event &event) {
 	// Check if the Ctrl key is down, so that we can trap cases where the
 	// user has the Ctrl key down, and has just released a special key
 	if (mod & KMOD_CTRL) {
-		if (sdlKeycode == 'm' ||	// Ctrl-m toggles mouse capture
-#if defined(MACOSX)
-			// Meta - Q, handled below
-#elif defined(POSIX)
-			sdlKeycode == 'q' ||	// On other *nix systems, Control-Q quits
-#else
-			sdlKeycode == 'z' ||	// Ctrl-z quit
-#endif
-			sdlKeycode == 'u')	// Ctrl-u toggles mute
+		if (sdlKeycode == 'm')	// Ctrl-m toggles mouse capture
 			return false;
 	}
 
-	// Same for other keys (Meta and Alt)
-#if defined(MACOSX)
-	if ((mod & KMOD_META) && sdlKeycode == 'q')
-		return false;	// On Macintosh, Cmd-Q quits
-#endif
-
 	// If we reached here, this isn't an event handled by handleKeyDown(), thus
 	// continue normally
 
diff --git a/engines/metaengine.cpp b/engines/metaengine.cpp
index 561cda4..060e4d5 100644
--- a/engines/metaengine.cpp
+++ b/engines/metaengine.cpp
@@ -48,23 +48,39 @@ const char *MetaEngine::getSavegamePattern(const char *target) const {
 }
 
 Common::Keymap *MetaEngine::initKeymap(const char *target) const {
-	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, "engine-default");
+	using namespace Common;
+
+	Keymap *const engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "engine-default");
 
 	// Since the game has multiple built-in keys for each of these anyway,
 	// this just attempts to remap one of them.
-	const Common::KeyActionEntry keyActionEntries[] = {
-		{ "PAUS", Common::KeyState(Common::KEYCODE_SPACE, ' ', 0),                   "SPACE",  _("Pause")     },
-		{ "SKCT", Common::KeyState(Common::KEYCODE_ESCAPE, Common::ASCII_ESCAPE, 0), "ESCAPE", _("Skip")      },
-		{ "SKLI", Common::KeyState(Common::KEYCODE_PERIOD, '.', 0),                  "PERIOD", _("Skip line") }
+	const KeyActionEntry keyActionEntries[] = {
+		{ "PAUS", KeyState(KEYCODE_SPACE, ' ', 0),           "SPACE",  _("Pause")     },
+		{ "SKCT", KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE, 0), "ESCAPE", _("Skip")      },
+		{ "SKLI", KeyState(KEYCODE_PERIOD, '.', 0),          "PERIOD", _("Skip line") }
 	};
 
 	for (uint i = 0; i < ARRAYSIZE(keyActionEntries); i++) {
-		Common::Action *const act = new Common::Action(keyActionEntries[i].id, keyActionEntries[i].description);
+		Action *const act = new Action(keyActionEntries[i].id, keyActionEntries[i].description);
 		act->setKeyEvent(keyActionEntries[i].ks);
 		act->addDefaultInputMapping(keyActionEntries[i].defaultHwId);
 		engineKeyMap->addAction(act);
 	}
 
+	Action *act;
+
+	act = new Action("LCLK", _("Left Click"));
+	act->setLeftClickEvent();
+	engineKeyMap->addAction(act);
+
+	act = new Action("MCLK", _("Middle Click"));
+	act->setMiddleClickEvent();
+	engineKeyMap->addAction(act);
+
+	act = new Action("RCLK", _("Right Click"));
+	act->setRightClickEvent();
+	engineKeyMap->addAction(act);
+
 	return engineKeyMap;
 }
 


Commit: be49fc4b9ac9c7b6e3039cde98270650ec69600a
    https://github.com/scummvm/scummvm/commit/be49fc4b9ac9c7b6e3039cde98270650ec69600a
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
SDL: Add a keymap for the graphics manager

Changed paths:
    backends/events/default/default-events.cpp
    backends/events/sdl/sdl-events.cpp
    backends/graphics/sdl/sdl-graphics.cpp
    backends/graphics/sdl/sdl-graphics.h
    backends/keymapper/hardware-input.cpp
    backends/platform/sdl/sdl.cpp
    backends/platform/sdl/sdl.h


diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp
index 6651075..51b357c 100644
--- a/backends/events/default/default-events.cpp
+++ b/backends/events/default/default-events.cpp
@@ -319,11 +319,6 @@ Common::Keymap *DefaultEventManager::getGlobalKeymap() {
 	globalKeymap->addAction(act);
 #endif
 
-	act = new Action("FULS", _("Toggle fullscreen"));
-	act->addDefaultInputMapping("A+RETURN");
-	act->setKeyEvent(KeyState(KEYCODE_RETURN, ASCII_RETURN, KBD_ALT));
-	globalKeymap->addAction(act);
-
 	act = new Action("MUTE", _("Toggle mute"));
 	act->addDefaultInputMapping("C+u");
 	act->setEvent(EVENT_MUTE);
diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp
index e61cadb..dae7397 100644
--- a/backends/events/sdl/sdl-events.cpp
+++ b/backends/events/sdl/sdl-events.cpp
@@ -753,14 +753,6 @@ bool SdlEventSource::handleKeyDown(SDL_Event &ev, Common::Event &event) {
 	if (_scrollLock)
 		event.kbd.flags |= Common::KBD_SCRL;
 
-	// Ctrl-m toggles mouse capture
-	if (event.kbd.hasFlags(Common::KBD_CTRL) && sdlKeycode == 'm') {
-		if (_graphicsManager) {
-			_graphicsManager->getWindow()->toggleMouseGrab();
-		}
-		return false;
-	}
-
 	if (remapKey(ev, event))
 		return true;
 
@@ -782,23 +774,10 @@ bool SdlEventSource::handleKeyUp(SDL_Event &ev, Common::Event &event) {
 	SDLKey sdlKeycode = obtainKeycode(ev.key.keysym);
 	SDLMod mod = SDL_GetModState();
 
-	// Check if this is an event handled by handleKeyDown(), and stop if it is
-
-	// Check if the Ctrl key is down, so that we can trap cases where the
-	// user has the Ctrl key down, and has just released a special key
-	if (mod & KMOD_CTRL) {
-		if (sdlKeycode == 'm')	// Ctrl-m toggles mouse capture
-			return false;
-	}
-
-	// If we reached here, this isn't an event handled by handleKeyDown(), thus
-	// continue normally
-
 	event.type = Common::EVENT_KEYUP;
 	event.kbd.keycode = SDLToOSystemKeycode(sdlKeycode);
 	event.kbd.ascii = mapKey(sdlKeycode, (SDLMod)ev.key.keysym.mod, 0);
 
-	// Ctrl-Alt-<key> will change the GFX mode
 	SDLModToOSystemKeyFlags(mod, event);
 
 	// Set the scroll lock sticky flag
diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp
index 97b4a5f..aad142e 100644
--- a/backends/graphics/sdl/sdl-graphics.cpp
+++ b/backends/graphics/sdl/sdl-graphics.cpp
@@ -24,9 +24,12 @@
 #include "backends/platform/sdl/sdl-sys.h"
 #include "backends/platform/sdl/sdl.h"
 #include "backends/events/sdl/sdl-events.h"
+#include "backends/keymapper/action.h"
+#include "backends/keymapper/keymap.h"
 #include "common/config-manager.h"
 #include "common/fs.h"
 #include "common/textconsole.h"
+#include "common/translation.h"
 #include "graphics/scaler/aspect.h"
 #ifdef USE_OSD
 #include "common/translation.h"
@@ -360,3 +363,102 @@ void SdlGraphicsManager::toggleFullScreen() {
 		displayMessageOnOSD(_("Windowed mode"));
 #endif
 }
+
+Common::Keymap *SdlGraphicsManager::getKeymap() {
+	using namespace Common;
+
+	Keymap *keymap = new Keymap(Keymap::kKeymapTypeGlobal, "sdl-graphics");
+	Action *act;
+
+	if (hasFeature(OSystem::kFeatureFullscreenMode)) {
+		act = new Action("FULS", _("Toggle fullscreen"));
+		act->addDefaultInputMapping("A+RETURN");
+		act->setKeyEvent(KeyState(KEYCODE_RETURN, ASCII_RETURN, KBD_ALT));
+		keymap->addAction(act);
+	}
+
+	act = new Action("CAPT", _("Toggle mouse capture"));
+	act->addDefaultInputMapping("C+m");
+	act->setKeyEvent(KeyState(KEYCODE_m, 'm', KBD_CTRL));
+	keymap->addAction(act);
+
+	act = new Action("SCRS", _("Save screenshot"));
+	act->addDefaultInputMapping("A+s");
+	act->setKeyEvent(KeyState(KEYCODE_s, 's', KBD_ALT));
+	keymap->addAction(act);
+
+	if (hasFeature(OSystem::kFeatureAspectRatioCorrection)) {
+		act = new Action("ASPT", _("Toggle aspect ratio correction"));
+		act->addDefaultInputMapping("C+A+a");
+		act->setKeyEvent(KeyState(KEYCODE_a, 'a', KBD_CTRL | KBD_ALT));
+		keymap->addAction(act);
+	}
+
+	if (hasFeature(OSystem::kFeatureFilteringMode)) {
+		act = new Action("FILT", _("Toggle linear filtered scaling"));
+		act->addDefaultInputMapping("C+A+f");
+		act->setKeyEvent(KeyState(KEYCODE_f, 'f', KBD_CTRL | KBD_ALT));
+		keymap->addAction(act);
+	}
+
+	if (hasFeature(OSystem::kFeatureStretchMode)) {
+		act = new Action("STCH", _("Cycle through stretch modes"));
+		act->addDefaultInputMapping("C+A+s");
+		act->setKeyEvent(KeyState(KEYCODE_s, 's', KBD_CTRL | KBD_ALT));
+		keymap->addAction(act);
+	}
+
+	act = new Action("SCL+", _("Increase the scale factor"));
+	act->addDefaultInputMapping("C+A+PLUS");
+	act->addDefaultInputMapping("C+A+KP_PLUS");
+	act->setKeyEvent(KeyState(KEYCODE_PLUS, '+', KBD_CTRL | KBD_ALT));
+	keymap->addAction(act);
+
+	act = new Action("SCL-", _("Decrease the scale factor"));
+	act->addDefaultInputMapping("C+A+MINUS");
+	act->addDefaultInputMapping("C+A+KP_MINUS");
+	act->setKeyEvent(KeyState(KEYCODE_MINUS, '-', KBD_CTRL | KBD_ALT));
+	keymap->addAction(act);
+
+	act = new Action("FLT1", _("Switch to nearest neighbour scaling"));
+	act->addDefaultInputMapping("C+A+1");
+	act->setKeyEvent(KeyState(KEYCODE_1, '1', KBD_CTRL | KBD_ALT));
+	keymap->addAction(act);
+
+	act = new Action("FLT2", _("Switch to AdvMame 2x/3x scaling"));
+	act->addDefaultInputMapping("C+A+2");
+	act->setKeyEvent(KeyState(KEYCODE_2, '2', KBD_CTRL | KBD_ALT));
+	keymap->addAction(act);
+
+	act = new Action("FLT3", _("Switch to HQ 2x/3x scaling"));
+	act->addDefaultInputMapping("C+A+3");
+	act->setKeyEvent(KeyState(KEYCODE_3, '3', KBD_CTRL | KBD_ALT));
+	keymap->addAction(act);
+
+	act = new Action("FLT4", _("Switch to 2xSai scaling"));
+	act->addDefaultInputMapping("C+A+4");
+	act->setKeyEvent(KeyState(KEYCODE_4, '4', KBD_CTRL | KBD_ALT));
+	keymap->addAction(act);
+
+	act = new Action("FLT5", _("Switch to Super2xSai scaling"));
+	act->addDefaultInputMapping("C+A+5");
+	act->setKeyEvent(KeyState(KEYCODE_5, '5', KBD_CTRL | KBD_ALT));
+	keymap->addAction(act);
+
+	act = new Action("FLT6", _("Switch to SuperEagle scaling"));
+	act->addDefaultInputMapping("C+A+6");
+	act->setKeyEvent(KeyState(KEYCODE_6, '6', KBD_CTRL | KBD_ALT));
+	keymap->addAction(act);
+
+	act = new Action("FLT7", _("Switch to Tv2x scaling"));
+	act->addDefaultInputMapping("C+A+7");
+	act->setKeyEvent(KeyState(KEYCODE_7, '7', KBD_CTRL | KBD_ALT));
+	keymap->addAction(act);
+
+	act = new Action("FLT8", _("Switch to DotMatrix scaling"));
+	act->addDefaultInputMapping("C+A+8");
+	act->setKeyEvent(KeyState(KEYCODE_8, '8', KBD_CTRL | KBD_ALT));
+	keymap->addAction(act);
+
+	return keymap;
+}
diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h
index 24c6d37..8201c9b 100644
--- a/backends/graphics/sdl/sdl-graphics.h
+++ b/backends/graphics/sdl/sdl-graphics.h
@@ -29,6 +29,10 @@
 #include "common/events.h"
 #include "common/rect.h"
 
+namespace Common {
+class Keymapper;
+}
+
 class SdlEventSource;
 
 #ifndef __SYMBIAN32__
@@ -134,6 +138,8 @@ public:
 
 	virtual void initSizeHint(const Graphics::ModeList &modes) override;
 
+	Common::Keymap *getKeymap();
+
 protected:
 	virtual int getGraphicsModeScale(int mode) const = 0;
 
diff --git a/backends/keymapper/hardware-input.cpp b/backends/keymapper/hardware-input.cpp
index fc27b1e..91d5b3c 100644
--- a/backends/keymapper/hardware-input.cpp
+++ b/backends/keymapper/hardware-input.cpp
@@ -205,6 +205,7 @@ static const KeyTableEntry defaultKeys[] = {
 	{0, KEYCODE_INVALID, 0}
 };
 
+// TODO: Add META and NUM_LOCK
 static const ModifierTableEntry defaultModifiers[] = {
 	{ 0, "", "" },
 	{ KBD_CTRL, "C+", "Ctrl+" },
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index b3436db..9ed28ea 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -389,6 +389,14 @@ void OSystem_SDL::fatalError() {
 	exit(1);
 }
 
+Common::KeymapArray OSystem_SDL::getGlobalKeymaps() {
+	Common::KeymapArray globalMaps = ModularBackend::getGlobalKeymaps();
+
+	SdlGraphicsManager *graphicsManager = dynamic_cast<SdlGraphicsManager *>(_graphicsManager);
+	globalMaps.push_back(graphicsManager->getKeymap());
+
+	return globalMaps;
+}
 
 void OSystem_SDL::logMessage(LogMessageType::Type type, const char *message) {
 	// First log to stdout/stderr
diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h
index d2912cb..bd7b538 100644
--- a/backends/platform/sdl/sdl.h
+++ b/backends/platform/sdl/sdl.h
@@ -63,6 +63,7 @@ public:
 	virtual void engineDone();
 	virtual void quit();
 	virtual void fatalError();
+	Common::KeymapArray getGlobalKeymaps() override;
 
 	// Logging
 	virtual void logMessage(LogMessageType::Type type, const char *message);


Commit: 13fbdb935a9be249ac6245ae4e12ed9220af15d8
    https://github.com/scummvm/scummvm/commit/13fbdb935a9be249ac6245ae4e12ed9220af15d8
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
KEYMAPPER: Use custom backend actions for the SDL graphics keymap

Changed paths:
    backends/graphics/openglsdl/openglsdl-graphics.cpp
    backends/graphics/openglsdl/openglsdl-graphics.h
    backends/graphics/sdl/sdl-graphics.cpp
    backends/graphics/sdl/sdl-graphics.h
    backends/graphics/surfacesdl/surfacesdl-graphics.cpp
    backends/graphics/surfacesdl/surfacesdl-graphics.h
    backends/keymapper/action.h
    backends/keymapper/remap-widget.cpp


diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index d959e02..5d91fbc 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -526,180 +526,164 @@ bool OpenGLSdlGraphicsManager::setupMode(uint width, uint height) {
 }
 
 bool OpenGLSdlGraphicsManager::notifyEvent(const Common::Event &event) {
-	switch (event.type) {
-	case Common::EVENT_KEYUP:
-		if (isHotkey(event))
-			return true;
+	if (event.type != Common::EVENT_CUSTOM_BACKEND_ACTION_START) {
+		return SdlGraphicsManager::notifyEvent(event);
+	}
 
-		break;
+	switch ((CustomEventAction) event.customType) {
+	case kActionIncreaseScaleFactor:
+	case kActionDecreaseScaleFactor: {
+		const int direction = event.customType == kActionIncreaseScaleFactor ? +1 : -1;
+
+		if (getFeatureState(OSystem::kFeatureFullscreenMode)) {
+			// In case we are in fullscreen we will choose the previous
+			// or next mode.
+
+			// In case no modes are available we do nothing.
+			if (_fullscreenVideoModes.empty()) {
+				return true;
+			}
 
-	case Common::EVENT_KEYDOWN:
-		if (event.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_ALT)) {
-			if (   event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS
-			    || event.kbd.keycode == Common::KEYCODE_KP_PLUS || event.kbd.keycode == Common::KEYCODE_KP_MINUS) {
-				// Ctrl+Alt+Plus/Minus Increase/decrease the size
-				const int direction = (event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_KP_PLUS) ? +1 : -1;
-
-				if (getFeatureState(OSystem::kFeatureFullscreenMode)) {
-					// In case we are in fullscreen we will choose the previous
-					// or next mode.
-
-					// In case no modes are available we do nothing.
-					if (_fullscreenVideoModes.empty()) {
-						return true;
-					}
-
-					// Look for the current mode.
-					VideoModeArray::const_iterator i = Common::find(_fullscreenVideoModes.begin(),
-					                                                _fullscreenVideoModes.end(),
-					                                                VideoMode(_desiredFullscreenWidth, _desiredFullscreenHeight));
-					if (i == _fullscreenVideoModes.end()) {
-						return true;
-					}
-
-					// Cycle through the modes in the specified direction.
-					if (direction > 0) {
-						++i;
-						if (i == _fullscreenVideoModes.end()) {
-							i = _fullscreenVideoModes.begin();
-						}
-					} else {
-						if (i == _fullscreenVideoModes.begin()) {
-							i = _fullscreenVideoModes.end();
-						}
-						--i;
-					}
-
-					_desiredFullscreenWidth  = i->width;
-					_desiredFullscreenHeight = i->height;
-
-					// Try to setup the mode.
-					if (!setupMode(_lastRequestedWidth, _lastRequestedHeight)) {
-						warning("OpenGLSdlGraphicsManager::notifyEvent: Fullscreen resize failed ('%s')", SDL_GetError());
-						g_system->quit();
-					}
-				} else {
-					// Calculate the next scaling setting. We approximate the
-					// current scale setting in case the user resized the
-					// window. Then we apply the direction change.
-					int windowWidth = 0, windowHeight = 0;
-					getWindowSizeFromSdl(&windowWidth, &windowHeight);
-					_graphicsScale = MAX<int>(windowWidth / _lastRequestedWidth, windowHeight / _lastRequestedHeight);
-					_graphicsScale = MAX<int>(_graphicsScale + direction, 1);
-
-					// Since we overwrite a user resize here we reset its
-					// flag here. This makes enabling AR smoother because it
-					// will change the window size like in surface SDL.
-					_gotResize = false;
-
-					// Try to setup the mode.
-					if (!setupMode(_lastRequestedWidth * _graphicsScale, _lastRequestedHeight * _graphicsScale)) {
-						warning("OpenGLSdlGraphicsManager::notifyEvent: Window resize failed ('%s')", SDL_GetError());
-						g_system->quit();
-					}
+			// Look for the current mode.
+			VideoModeArray::const_iterator i = Common::find(_fullscreenVideoModes.begin(),
+			                                                _fullscreenVideoModes.end(),
+			                                                VideoMode(_desiredFullscreenWidth, _desiredFullscreenHeight));
+			if (i == _fullscreenVideoModes.end()) {
+				return true;
+			}
+
+			// Cycle through the modes in the specified direction.
+			if (direction > 0) {
+				++i;
+				if (i == _fullscreenVideoModes.end()) {
+					i = _fullscreenVideoModes.begin();
+				}
+			} else {
+				if (i == _fullscreenVideoModes.begin()) {
+					i = _fullscreenVideoModes.end();
 				}
+				--i;
+			}
+
+			_desiredFullscreenWidth  = i->width;
+			_desiredFullscreenHeight = i->height;
+
+			// Try to setup the mode.
+			if (!setupMode(_lastRequestedWidth, _lastRequestedHeight)) {
+				warning("OpenGLSdlGraphicsManager::notifyEvent: Fullscreen resize failed ('%s')", SDL_GetError());
+				g_system->quit();
+			}
+		} else {
+			// Calculate the next scaling setting. We approximate the
+			// current scale setting in case the user resized the
+			// window. Then we apply the direction change.
+			int windowWidth = 0, windowHeight = 0;
+			getWindowSizeFromSdl(&windowWidth, &windowHeight);
+			_graphicsScale = MAX<int>(windowWidth / _lastRequestedWidth, windowHeight / _lastRequestedHeight);
+			_graphicsScale = MAX<int>(_graphicsScale + direction, 1);
+
+			// Since we overwrite a user resize here we reset its
+			// flag here. This makes enabling AR smoother because it
+			// will change the window size like in surface SDL.
+			_gotResize = false;
+
+			// Try to setup the mode.
+			if (!setupMode(_lastRequestedWidth * _graphicsScale, _lastRequestedHeight * _graphicsScale)) {
+				warning("OpenGLSdlGraphicsManager::notifyEvent: Window resize failed ('%s')", SDL_GetError());
+				g_system->quit();
+			}
+		}
 
 #ifdef USE_OSD
-				int windowWidth = 0, windowHeight = 0;
-				getWindowSizeFromSdl(&windowWidth, &windowHeight);
-				const Common::String osdMsg = Common::String::format(_("Resolution: %dx%d"), windowWidth, windowHeight);
-				displayMessageOnOSD(osdMsg.c_str());
+		int windowWidth = 0, windowHeight = 0;
+		getWindowSizeFromSdl(&windowWidth, &windowHeight);
+		const Common::String osdMsg = Common::String::format(_("Resolution: %dx%d"), windowWidth, windowHeight);
+		displayMessageOnOSD(osdMsg.c_str());
 #endif
 
-				return true;
-			} else if (event.kbd.keycode == Common::KEYCODE_a) {
-				// In case the user changed the window size manually we will
-				// not change the window size again here.
-				_ignoreLoadVideoMode = _gotResize;
+		return true;
+	}
 
-				// Ctrl+Alt+a toggles the aspect ratio correction state.
-				beginGFXTransaction();
-					setFeatureState(OSystem::kFeatureAspectRatioCorrection, !getFeatureState(OSystem::kFeatureAspectRatioCorrection));
-				endGFXTransaction();
+	case kActionToggleAspectRatioCorrection:
+		// In case the user changed the window size manually we will
+		// not change the window size again here.
+		_ignoreLoadVideoMode = _gotResize;
 
-				// Make sure we do not ignore the next resize. This
-				// effectively checks whether loadVideoMode has been called.
-				assert(!_ignoreLoadVideoMode);
+		// Toggles the aspect ratio correction state.
+		beginGFXTransaction();
+			setFeatureState(OSystem::kFeatureAspectRatioCorrection, !getFeatureState(OSystem::kFeatureAspectRatioCorrection));
+		endGFXTransaction();
+
+		// Make sure we do not ignore the next resize. This
+		// effectively checks whether loadVideoMode has been called.
+		assert(!_ignoreLoadVideoMode);
 
 #ifdef USE_OSD
-				if (getFeatureState(OSystem::kFeatureAspectRatioCorrection))
-					displayMessageOnOSD(_("Enabled aspect ratio correction"));
-				else
-					displayMessageOnOSD(_("Disabled aspect ratio correction"));
+		if (getFeatureState(OSystem::kFeatureAspectRatioCorrection))
+			displayMessageOnOSD(_("Enabled aspect ratio correction"));
+		else
+			displayMessageOnOSD(_("Disabled aspect ratio correction"));
 #endif
 
-				return true;
-			} else if (event.kbd.keycode == Common::KEYCODE_f) {
-				// Never ever try to resize the window when we simply want to enable or disable filtering.
-				// This assures that the window size does not change.
-				_ignoreLoadVideoMode = true;
+		return true;
 
-				// Ctrl+Alt+f toggles filtering on/off
-				beginGFXTransaction();
-					setFeatureState(OSystem::kFeatureFilteringMode, !getFeatureState(OSystem::kFeatureFilteringMode));
-				endGFXTransaction();
+	case kActionToggleFilteredScaling:
+		// Never ever try to resize the window when we simply want to enable or disable filtering.
+		// This assures that the window size does not change.
+		_ignoreLoadVideoMode = true;
 
-				// Make sure we do not ignore the next resize. This
-				// effectively checks whether loadVideoMode has been called.
-				assert(!_ignoreLoadVideoMode);
+		// Ctrl+Alt+f toggles filtering on/off
+		beginGFXTransaction();
+			setFeatureState(OSystem::kFeatureFilteringMode, !getFeatureState(OSystem::kFeatureFilteringMode));
+		endGFXTransaction();
+
+		// Make sure we do not ignore the next resize. This
+		// effectively checks whether loadVideoMode has been called.
+		assert(!_ignoreLoadVideoMode);
 
 #ifdef USE_OSD
-				if (getFeatureState(OSystem::kFeatureFilteringMode)) {
-					displayMessageOnOSD(_("Filtering enabled"));
-				} else {
-					displayMessageOnOSD(_("Filtering disabled"));
-				}
+		if (getFeatureState(OSystem::kFeatureFilteringMode)) {
+			displayMessageOnOSD(_("Filtering enabled"));
+		} else {
+			displayMessageOnOSD(_("Filtering disabled"));
+		}
 #endif
 
-				return true;
-			} else if (event.kbd.keycode == Common::KEYCODE_s) {
-				// Never try to resize the window when changing the scaling mode.
-				_ignoreLoadVideoMode = true;
-
-				// Ctrl+Alt+s cycles through stretch mode
-				int index = 0;
-				const OSystem::GraphicsMode *stretchModes = getSupportedStretchModes();
-				const OSystem::GraphicsMode *sm = stretchModes;
-				while (sm->name) {
-					if (sm->id == getStretchMode())
-						break;
-					sm++;
-					index++;
-				}
-				index++;
-				if (!stretchModes[index].name)
-					index = 0;
-				beginGFXTransaction();
-				setStretchMode(stretchModes[index].id);
-				endGFXTransaction();
+		return true;
+
+	case kActionCycleStretchMode: {
+		// Never try to resize the window when changing the scaling mode.
+		_ignoreLoadVideoMode = true;
+
+		// Ctrl+Alt+s cycles through stretch mode
+		int index = 0;
+		const OSystem::GraphicsMode *stretchModes = getSupportedStretchModes();
+		const OSystem::GraphicsMode *sm = stretchModes;
+		while (sm->name) {
+			if (sm->id == getStretchMode())
+				break;
+			sm++;
+			index++;
+		}
+		index++;
+		if (!stretchModes[index].name)
+			index = 0;
+		beginGFXTransaction();
+		setStretchMode(stretchModes[index].id);
+		endGFXTransaction();
 
 #ifdef USE_OSD
-				Common::String message = Common::String::format("%s: %s",
-					_("Stretch mode"),
-					_(stretchModes[index].description)
-					);
-				displayMessageOnOSD(message.c_str());
+		Common::String message = Common::String::format("%s: %s",
+			_("Stretch mode"),
+			_(stretchModes[index].description)
+			);
+		displayMessageOnOSD(message.c_str());
 #endif
-				return true;
-			}
-		}
-		// Fall through
 
-	default:
-		break;
+		return true;
 	}
 
-	return SdlGraphicsManager::notifyEvent(event);
-}
-
-bool OpenGLSdlGraphicsManager::isHotkey(const Common::Event &event) const {
-	if (event.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_ALT)) {
-		return    event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS
-		       || event.kbd.keycode == Common::KEYCODE_KP_PLUS || event.kbd.keycode == Common::KEYCODE_KP_MINUS
-		       || event.kbd.keycode == Common::KEYCODE_a
-		       || event.kbd.keycode == Common::KEYCODE_f
-		       || event.kbd.keycode == Common::KEYCODE_s;
+	default:
+		return SdlGraphicsManager::notifyEvent(event);
 	}
-
-	return false;
 }
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h
index 929adc9..0db24c1 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.h
+++ b/backends/graphics/openglsdl/openglsdl-graphics.h
@@ -114,8 +114,6 @@ private:
 
 	uint _desiredFullscreenWidth;
 	uint _desiredFullscreenHeight;
-
-	bool isHotkey(const Common::Event &event) const;
 };
 
 #endif
diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp
index aad142e..2c68c0f 100644
--- a/backends/graphics/sdl/sdl-graphics.cpp
+++ b/backends/graphics/sdl/sdl-graphics.cpp
@@ -315,38 +315,26 @@ void SdlGraphicsManager::saveScreenshot() {
 }
 
 bool SdlGraphicsManager::notifyEvent(const Common::Event &event) {
-	switch ((int)event.type) {
-	case Common::EVENT_KEYDOWN:
-		// Alt-Return and Alt-Enter toggle full screen mode
-		if (event.kbd.hasFlags(Common::KBD_ALT) &&
-			(event.kbd.keycode == Common::KEYCODE_RETURN ||
-			 event.kbd.keycode == Common::KEYCODE_KP_ENTER)) {
-			toggleFullScreen();
-			return true;
-		}
-
-		// Alt-S: Create a screenshot
-		if (event.kbd.hasFlags(Common::KBD_ALT) && event.kbd.keycode == 's') {
-			saveScreenshot();
-			return true;
-		}
+	if (event.type != Common::EVENT_CUSTOM_BACKEND_ACTION_START) {
+		return false;
+	}
 
-		break;
+	switch ((CustomEventAction) event.customType) {
+	case kActionToggleMouseCapture:
+		getWindow()->toggleMouseGrab();
+		return true;
 
-	case Common::EVENT_KEYUP:
-		if (event.kbd.hasFlags(Common::KBD_ALT)) {
-			return    event.kbd.keycode == Common::KEYCODE_RETURN
-			       || event.kbd.keycode == Common::KEYCODE_KP_ENTER
-			       || event.kbd.keycode == Common::KEYCODE_s;
-		}
+	case kActionToggleFullscreen:
+		toggleFullScreen();
+		return true;
 
-		break;
+	case kActionSaveScreenshot:
+		saveScreenshot();
+		return true;
 
 	default:
-		break;
+		return false;
 	}
-
-	return false;
 }
 
 void SdlGraphicsManager::toggleFullScreen() {
@@ -373,92 +361,79 @@ Common::Keymap *SdlGraphicsManager::getKeymap() {
 	if (hasFeature(OSystem::kFeatureFullscreenMode)) {
 		act = new Action("FULS", _("Toggle fullscreen"));
 		act->addDefaultInputMapping("A+RETURN");
-		act->setKeyEvent(KeyState(KEYCODE_RETURN, ASCII_RETURN, KBD_ALT));
+		act->setCustomBackendActionEvent(kActionToggleFullscreen);
 		keymap->addAction(act);
 	}
 
 	act = new Action("CAPT", _("Toggle mouse capture"));
 	act->addDefaultInputMapping("C+m");
-	act->setKeyEvent(KeyState(KEYCODE_m, 'm', KBD_CTRL));
+	act->setCustomBackendActionEvent(kActionToggleMouseCapture);
 	keymap->addAction(act);
 
 	act = new Action("SCRS", _("Save screenshot"));
 	act->addDefaultInputMapping("A+s");
-	act->setKeyEvent(KeyState(KEYCODE_s, 's', KBD_ALT));
+	act->setCustomBackendActionEvent(kActionSaveScreenshot);
 	keymap->addAction(act);
 
 	if (hasFeature(OSystem::kFeatureAspectRatioCorrection)) {
 		act = new Action("ASPT", _("Toggle aspect ratio correction"));
 		act->addDefaultInputMapping("C+A+a");
-		act->setKeyEvent(KeyState(KEYCODE_a, 'a', KBD_CTRL | KBD_ALT));
+		act->setCustomBackendActionEvent(kActionToggleAspectRatioCorrection);
 		keymap->addAction(act);
 	}
 
 	if (hasFeature(OSystem::kFeatureFilteringMode)) {
 		act = new Action("FILT", _("Toggle linear filtered scaling"));
 		act->addDefaultInputMapping("C+A+f");
-		act->setKeyEvent(KeyState(KEYCODE_f, 'f', KBD_CTRL | KBD_ALT));
+		act->setCustomBackendActionEvent(kActionToggleFilteredScaling);
 		keymap->addAction(act);
 	}
 
 	if (hasFeature(OSystem::kFeatureStretchMode)) {
 		act = new Action("STCH", _("Cycle through stretch modes"));
 		act->addDefaultInputMapping("C+A+s");
-		act->setKeyEvent(KeyState(KEYCODE_s, 's', KBD_CTRL | KBD_ALT));
+		act->setCustomBackendActionEvent(kActionCycleStretchMode);
 		keymap->addAction(act);
 	}
 
 	act = new Action("SCL+", _("Increase the scale factor"));
 	act->addDefaultInputMapping("C+A+PLUS");
 	act->addDefaultInputMapping("C+A+KP_PLUS");
-	act->setKeyEvent(KeyState(KEYCODE_PLUS, '+', KBD_CTRL | KBD_ALT));
+	act->setCustomBackendActionEvent(kActionIncreaseScaleFactor);
 	keymap->addAction(act);
 
 	act = new Action("SCL-", _("Decrease the scale factor"));
 	act->addDefaultInputMapping("C+A+MINUS");
 	act->addDefaultInputMapping("C+A+KP_MINUS");
-	act->setKeyEvent(KeyState(KEYCODE_MINUS, '-', KBD_CTRL | KBD_ALT));
-	keymap->addAction(act);
-
-	act = new Action("FLT1", _("Switch to nearest neighbour scaling"));
-	act->addDefaultInputMapping("C+A+1");
-	act->setKeyEvent(KeyState(KEYCODE_1, '1', KBD_CTRL | KBD_ALT));
-	keymap->addAction(act);
-
-	act = new Action("FLT2", _("Switch to AdvMame 2x/3x scaling"));
-	act->addDefaultInputMapping("C+A+2");
-	act->setKeyEvent(KeyState(KEYCODE_2, '2', KBD_CTRL | KBD_ALT));
+	act->setCustomBackendActionEvent(kActionDecreaseScaleFactor);
 	keymap->addAction(act);
 
-	act = new Action("FLT3", _("Switch to HQ 2x/3x scaling"));
-	act->addDefaultInputMapping("C+A+3");
-	act->setKeyEvent(KeyState(KEYCODE_3, '3', KBD_CTRL | KBD_ALT));
-	keymap->addAction(act);
-
-	act = new Action("FLT4", _("Switch to 2xSai scaling"));
-	act->addDefaultInputMapping("C+A+4");
-	act->setKeyEvent(KeyState(KEYCODE_4, '4', KBD_CTRL | KBD_ALT));
-	keymap->addAction(act);
-
-	act = new Action("FLT5", _("Switch to Super2xSai scaling"));
-	act->addDefaultInputMapping("C+A+5");
-	act->setKeyEvent(KeyState(KEYCODE_5, '5', KBD_CTRL | KBD_ALT));
-	keymap->addAction(act);
-
-	act = new Action("FLT6", _("Switch to SuperEagle scaling"));
-	act->addDefaultInputMapping("C+A+6");
-	act->setKeyEvent(KeyState(KEYCODE_6, '6', KBD_CTRL | KBD_ALT));
-	keymap->addAction(act);
-
-	act = new Action("FLT7", _("Switch to Tv2x scaling"));
-	act->addDefaultInputMapping("C+A+7");
-	act->setKeyEvent(KeyState(KEYCODE_7, '7', KBD_CTRL | KBD_ALT));
-	keymap->addAction(act);
-
-	act = new Action("FLT8", _("Switch to DotMatrix scaling"));
-	act->addDefaultInputMapping("C+A+8");
-	act->setKeyEvent(KeyState(KEYCODE_8, '8', KBD_CTRL | KBD_ALT));
-	keymap->addAction(act);
+#ifdef USE_SCALERS
+	struct ActionEntry {
+		const char *id;
+		const char *description;
+	};
+	static const ActionEntry filters[] = {
+			{ "FLT1", _s("Switch to nearest neighbour scaling") },
+			{ "FLT2", _s("Switch to AdvMame 2x/3x scaling")     },
+#ifdef USE_HQ_SCALERS
+			{ "FLT3", _s("Switch to HQ 2x/3x scaling")          },
+#endif
+			{ "FLT4", _s("Switch to 2xSai scaling")             },
+			{ "FLT5", _s("Switch to Super2xSai scaling")        },
+			{ "FLT6", _s("Switch to SuperEagle scaling")        },
+			{ "FLT7", _s("Switch to TV 2x scaling")             },
+			{ "FLT8", _s("Switch to DotMatrix scaling")         }
+	};
+
+	for (uint i = 0; i < ARRAYSIZE(filters); i++) {
+		act = new Action(filters[i].id, filters[i].description);
+		act->addDefaultInputMapping(String::format("C+A+%d", i + 1));
+		act->addDefaultInputMapping(String::format("C+A+KP%d", i + 1));
+		act->setCustomBackendActionEvent(kActionSetScaleFilter1 + i);
+		keymap->addAction(act);
+	}
+#endif
 
 	return keymap;
 }
diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h
index 8201c9b..401f523 100644
--- a/backends/graphics/sdl/sdl-graphics.h
+++ b/backends/graphics/sdl/sdl-graphics.h
@@ -29,10 +29,6 @@
 #include "common/events.h"
 #include "common/rect.h"
 
-namespace Common {
-class Keymapper;
-}
-
 class SdlEventSource;
 
 #ifndef __SYMBIAN32__
@@ -141,6 +137,25 @@ public:
 	Common::Keymap *getKeymap();
 
 protected:
+	enum CustomEventAction {
+		kActionToggleFullscreen = 100,
+		kActionToggleMouseCapture,
+		kActionSaveScreenshot,
+		kActionToggleAspectRatioCorrection,
+		kActionToggleFilteredScaling,
+		kActionCycleStretchMode,
+		kActionIncreaseScaleFactor,
+		kActionDecreaseScaleFactor,
+		kActionSetScaleFilter1,
+		kActionSetScaleFilter2,
+		kActionSetScaleFilter3,
+		kActionSetScaleFilter4,
+		kActionSetScaleFilter5,
+		kActionSetScaleFilter6,
+		kActionSetScaleFilter7,
+		kActionSetScaleFilter8
+	};
+
 	virtual int getGraphicsModeScale(int mode) const = 0;
 
 	bool defaultGraphicsModeConfig() const;
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
index bb7221d..9f92840 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
@@ -2517,9 +2517,67 @@ void SurfaceSdlGraphicsManager::handleResizeImpl(const int width, const int heig
 	recalculateDisplayAreas();
 }
 
-bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {
-	// Ctrl-Alt-a toggles aspect ratio correction
-	if (key == 'a') {
+void SurfaceSdlGraphicsManager::handleScalerHotkeys(int scalefactor, int scalerType) {
+	assert(scalerType >= 0 && scalerType < ARRAYSIZE(s_gfxModeSwitchTable));
+
+	int factor = CLIP(scalefactor - 1, 0, 4);
+
+	while (s_gfxModeSwitchTable[scalerType][factor] < 0) {
+		assert(factor > 0);
+		factor--;
+	}
+
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+	bool sizeChanged = _videoMode.scaleFactor != factor;
+#endif
+
+	int newMode = s_gfxModeSwitchTable[scalerType][factor];
+	if (newMode >= 0) {
+		_scalerType = scalerType;
+
+		beginGFXTransaction();
+			setGraphicsMode(newMode);
+		endGFXTransaction();
+#ifdef USE_OSD
+		const char *newScalerName = 0;
+		const OSystem::GraphicsMode *g = getSupportedGraphicsModes();
+		while (g->name) {
+			if (g->id == _videoMode.mode) {
+				newScalerName = g->description;
+				break;
+			}
+			g++;
+		}
+		if (newScalerName) {
+			const Common::String message = Common::String::format(
+				"%s %s\n%d x %d -> %d x %d",
+				_("Active graphics filter:"),
+				newScalerName,
+				_videoMode.screenWidth, _videoMode.screenHeight,
+				_hwScreen->w, _hwScreen->h);
+			displayMessageOnOSD(message.c_str());
+		}
+#endif
+
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+		if (sizeChanged) {
+			// Forcibly resizing the window here since a user switching scaler
+			// size will not normally cause the window to update
+			_window->createOrUpdateWindow(_hwScreen->w, _hwScreen->h, _lastFlags);
+		}
+#endif
+
+		internUpdateScreen();
+	}
+}
+
+bool SurfaceSdlGraphicsManager::notifyEvent(const Common::Event &event) {
+	if (event.type != Common::EVENT_CUSTOM_BACKEND_ACTION_START) {
+		return SdlGraphicsManager::notifyEvent(event);
+	}
+
+	switch ((CustomEventAction) event.customType) {
+	case kActionToggleAspectRatioCorrection: {
 		beginGFXTransaction();
 			setFeatureState(OSystem::kFeatureAspectRatioCorrection, !_videoMode.aspectRatioCorrection);
 		endGFXTransaction();
@@ -2527,26 +2585,26 @@ bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {
 		Common::String message;
 		if (_videoMode.aspectRatioCorrection)
 			message = Common::String::format("%s\n%d x %d -> %d x %d",
-				_("Enabled aspect ratio correction"),
-				_videoMode.screenWidth, _videoMode.screenHeight,
-				_hwScreen->w, _hwScreen->h
-				);
+			                                 _("Enabled aspect ratio correction"),
+			                                 _videoMode.screenWidth, _videoMode.screenHeight,
+			                                 _hwScreen->w, _hwScreen->h
+			);
 		else
 			message = Common::String::format("%s\n%d x %d -> %d x %d",
-				_("Disabled aspect ratio correction"),
-				_videoMode.screenWidth, _videoMode.screenHeight,
-				_hwScreen->w, _hwScreen->h
-				);
+			                                 _("Disabled aspect ratio correction"),
+			                                 _videoMode.screenWidth, _videoMode.screenHeight,
+			                                 _hwScreen->w, _hwScreen->h
+			);
 		displayMessageOnOSD(message.c_str());
 #endif
 		internUpdateScreen();
 		return true;
 	}
 
-	// Ctrl-Alt-f toggles filtering
-	if (key == 'f') {
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+	case kActionToggleFilteredScaling:
 		beginGFXTransaction();
-		setFeatureState(OSystem::kFeatureFilteringMode, !_videoMode.filtering);
+			setFeatureState(OSystem::kFeatureFilteringMode, !_videoMode.filtering);
 		endGFXTransaction();
 #ifdef USE_OSD
 		if (getFeatureState(OSystem::kFeatureFilteringMode)) {
@@ -2558,11 +2616,10 @@ bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {
 		_forceRedraw = true;
 		internUpdateScreen();
 		return true;
-	}
+#endif
 
 #if SDL_VERSION_ATLEAST(2, 0, 0)
-	// Ctrl+Alt+s cycles through scaling mode (0 to 3)
-	if (key == 's') {
+	case kActionCycleStretchMode: {
 		int index = 0;
 		const OSystem::GraphicsMode *sm = s_supportedStretchModes;
 		while (sm->name) {
@@ -2576,142 +2633,44 @@ bool SurfaceSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {
 			index = 0;
 
 		beginGFXTransaction();
-		setStretchMode(s_supportedStretchModes[index].id);
+			setStretchMode(s_supportedStretchModes[index].id);
 		endGFXTransaction();
 
 #ifdef USE_OSD
 		Common::String message = Common::String::format("%s: %s",
-			_("Stretch mode"),
-			_(s_supportedStretchModes[index].description)
-			);
+		                                                _("Stretch mode"),
+		                                                _(s_supportedStretchModes[index].description)
+		);
 		displayMessageOnOSD(message.c_str());
 #endif
 		_forceRedraw = true;
 		internUpdateScreen();
 		return true;
-	}
-#endif
-
-	int newMode = -1;
-	int factor = _videoMode.scaleFactor - 1;
-	SDLKey sdlKey = (SDLKey)key;
-
-#if SDL_VERSION_ATLEAST(2, 0, 0)
-	bool sizeChanged = false;
-#endif
-
-	// Increase/decrease the scale factor
-	if (sdlKey == SDLK_EQUALS || sdlKey == SDLK_PLUS || sdlKey == SDLK_MINUS ||
-		sdlKey == SDLK_KP_PLUS || sdlKey == SDLK_KP_MINUS) {
-		factor += (sdlKey == SDLK_MINUS || sdlKey == SDLK_KP_MINUS) ? -1 : +1;
-		if (0 <= factor && factor <= 3) {
-			newMode = s_gfxModeSwitchTable[_scalerType][factor];
-#if SDL_VERSION_ATLEAST(2, 0, 0)
-			sizeChanged = true;
 #endif
-		}
-	}
-
-	const bool isNormalNumber = (SDLK_1 <= sdlKey && sdlKey <= SDLK_9);
-	const bool isKeypadNumber = (SDLK_KP1 <= sdlKey && sdlKey <= SDLK_KP9);
-	if (isNormalNumber || isKeypadNumber) {
-		_scalerType = sdlKey - (isNormalNumber ? SDLK_1 : SDLK_KP1);
-		if (_scalerType >= ARRAYSIZE(s_gfxModeSwitchTable))
-			return false;
-
-		while (s_gfxModeSwitchTable[_scalerType][factor] < 0) {
-			assert(factor > 0);
-			factor--;
-		}
-		newMode = s_gfxModeSwitchTable[_scalerType][factor];
 	}
 
-	if (newMode >= 0) {
-		beginGFXTransaction();
-			setGraphicsMode(newMode);
-		endGFXTransaction();
-#ifdef USE_OSD
-		const char *newScalerName = 0;
-		const OSystem::GraphicsMode *g = getSupportedGraphicsModes();
-		while (g->name) {
-			if (g->id == _videoMode.mode) {
-				newScalerName = g->description;
-				break;
-			}
-			g++;
-		}
-		if (newScalerName) {
-			const Common::String message = Common::String::format(
-				"%s %s\n%d x %d -> %d x %d",
-				_("Active graphics filter:"),
-				newScalerName,
-				_videoMode.screenWidth, _videoMode.screenHeight,
-				_hwScreen->w, _hwScreen->h);
-			displayMessageOnOSD(message.c_str());
-		}
-#endif
-
-#if SDL_VERSION_ATLEAST(2, 0, 0)
-		if (sizeChanged) {
-			// Forcibly resizing the window here since a user switching scaler
-			// size will not normally cause the window to update
-			_window->createOrUpdateWindow(_hwScreen->w, _hwScreen->h, _lastFlags);
-		}
-#endif
-
-		internUpdateScreen();
-
+	case kActionIncreaseScaleFactor:
+		handleScalerHotkeys(_videoMode.scaleFactor + 1, _scalerType);
 		return true;
-	} else {
-		return false;
-	}
-}
-
-bool SurfaceSdlGraphicsManager::isScalerHotkey(const Common::Event &event) {
-	if ((event.kbd.flags & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) {
-		const bool isNormalNumber = (Common::KEYCODE_1 <= event.kbd.keycode && event.kbd.keycode <= Common::KEYCODE_9);
-		const bool isKeypadNumber = (Common::KEYCODE_KP1 <= event.kbd.keycode && event.kbd.keycode <= Common::KEYCODE_KP9);
-		const bool isScaleKey = (event.kbd.keycode == Common::KEYCODE_EQUALS || event.kbd.keycode == Common::KEYCODE_PLUS || event.kbd.keycode == Common::KEYCODE_MINUS ||
-			event.kbd.keycode == Common::KEYCODE_KP_PLUS || event.kbd.keycode == Common::KEYCODE_KP_MINUS);
 
-		if (isNormalNumber || isKeypadNumber) {
-			int keyValue = event.kbd.keycode - (isNormalNumber ? Common::KEYCODE_1 : Common::KEYCODE_KP1);
-			if (keyValue >= ARRAYSIZE(s_gfxModeSwitchTable))
-				return false;
-		}
-		if (event.kbd.keycode == 'f')
-			return true;
-#if SDL_VERSION_ATLEAST(2, 0, 0)
-		if (event.kbd.keycode == 's')
-			return true;
-#endif
-		return (isScaleKey || event.kbd.keycode == 'a');
-	}
-	return false;
-}
-
-bool SurfaceSdlGraphicsManager::notifyEvent(const Common::Event &event) {
-	switch ((int)event.type) {
-	case Common::EVENT_KEYDOWN:
-		// Ctrl-Alt-<key> will change the GFX mode
-		if (event.kbd.hasFlags(Common::KBD_CTRL|Common::KBD_ALT)) {
-			if (handleScalerHotkeys(event.kbd.keycode))
-				return true;
-		}
-
-		break;
-
-	case Common::EVENT_KEYUP:
-		if (isScalerHotkey(event))
-			return true;
+	case kActionDecreaseScaleFactor:
+		handleScalerHotkeys(_videoMode.scaleFactor - 1, _scalerType);
+		return true;
 
-		break;
+	case kActionSetScaleFilter1:
+	case kActionSetScaleFilter2:
+	case kActionSetScaleFilter3:
+	case kActionSetScaleFilter4:
+	case kActionSetScaleFilter5:
+	case kActionSetScaleFilter6:
+	case kActionSetScaleFilter7:
+	case kActionSetScaleFilter8:
+		handleScalerHotkeys(_videoMode.scaleFactor, event.customType - kActionSetScaleFilter1);
+		return true;
 
 	default:
-		break;
+		return SdlGraphicsManager::notifyEvent(event);
 	}
-
-	return SdlGraphicsManager::notifyEvent(event);
 }
 
 void SurfaceSdlGraphicsManager::notifyVideoExpose() {
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.h b/backends/graphics/surfacesdl/surfacesdl-graphics.h
index 6b8ae36..d4e6dc1 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.h
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.h
@@ -430,8 +430,7 @@ protected:
 
 private:
 	void setFullscreenMode(bool enable);
-	bool handleScalerHotkeys(Common::KeyCode key);
-	bool isScalerHotkey(const Common::Event &event);
+	void handleScalerHotkeys(int scalefactor, int scalerType);
 
 	/**
 	 * Converts the given point from the overlay's coordinate space to the
diff --git a/backends/keymapper/action.h b/backends/keymapper/action.h
index c777cda..94bd7f7 100644
--- a/backends/keymapper/action.h
+++ b/backends/keymapper/action.h
@@ -62,6 +62,12 @@ public:
 		event.type = evtType;
 	}
 
+	void setCustomBackendActionEvent(const CustomEventType evtType) {
+		event = Event();
+		event.type = EVENT_CUSTOM_BACKEND_ACTION_START;
+		event.customType = evtType;
+	}
+
 	void setKeyEvent(const KeyState &ks) {
 		event = Event();
 		event.type = EVENT_KEYDOWN;
diff --git a/backends/keymapper/remap-widget.cpp b/backends/keymapper/remap-widget.cpp
index 35ce5ad..d96b737 100644
--- a/backends/keymapper/remap-widget.cpp
+++ b/backends/keymapper/remap-widget.cpp
@@ -195,6 +195,7 @@ void RemapWidget::startRemapping(uint i) {
 	_remapInputWatcher->startWatching();
 
 	_actions[i].keyButton->setLabel("...");
+	_actions[i].keyButton->setTooltip("");
 	_actions[i].keyButton->markAsDirty();
 }
 
@@ -275,6 +276,7 @@ void RemapWidget::refreshKeymap() {
 			row.keyButton->setTooltip(keysLabel);
 		} else {
 			row.keyButton->setLabel("-");
+			row.keyButton->setTooltip("");
 		}
 
 		// I18N: Button to reset key mapping to defaults


Commit: df4bf6556cb4cba62f390b1d0089c641c8e7696e
    https://github.com/scummvm/scummvm/commit/df4bf6556cb4cba62f390b1d0089c641c8e7696e
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
KEYMAPPER: Introduce custom engine actions

Custom engine actions are a new type of event the Keymapper can produce.
When an engine declares its keymap, it can declare it wants to receive
custom action events when the corresponding key is pressed, instead of
the originating hardware input events.

This system allows:
* Key bindings to be specified only once when declaring the keymap,
  instead of twice (when handling the events).
* To truly rebind keys in the keymaps dialog. When using traditional
  event mapping, the keymapper remaps the user keypress to the keypress
  expected by the game engine to perform the action. However, the engine
  still accepts the original keys.

The new concept of 'standard actions' defines a set of engine actions
that are commonly available in the games supported by ScummVM. Backends
can define default bindings for the standard actions to hardware
specific input devices.

Changed paths:
  A backends/keymapper/standard-actions.cpp
  A backends/keymapper/standard-actions.h
    backends/keymapper/action.cpp
    backends/keymapper/action.h
    backends/keymapper/keymap.cpp
    backends/keymapper/keymap.h
    backends/keymapper/keymapper.cpp
    backends/module.mk
    backends/platform/maemo/maemo.cpp
    common/EventDispatcher.cpp
    common/events.h


diff --git a/backends/keymapper/action.cpp b/backends/keymapper/action.cpp
index 4c8904d..ecb4f47 100644
--- a/backends/keymapper/action.cpp
+++ b/backends/keymapper/action.cpp
@@ -33,6 +33,10 @@ Action::Action(const char *i, const String &des) :
 }
 
 void Action::addDefaultInputMapping(const String &hwId) {
+	if (hwId.empty()) {
+		return;
+	}
+
 	// Don't allow an input to map to the same action multiple times
 	Array<String>::const_iterator found = find(_defaultInputMapping.begin(), _defaultInputMapping.end(), hwId);
 	if (found == _defaultInputMapping.end()) {
diff --git a/backends/keymapper/action.h b/backends/keymapper/action.h
index 94bd7f7..11e4b82 100644
--- a/backends/keymapper/action.h
+++ b/backends/keymapper/action.h
@@ -68,6 +68,12 @@ public:
 		event.customType = evtType;
 	}
 
+	void setCustomEngineActionEvent(const CustomEventType evtType) {
+		event = Event();
+		event.type = EVENT_CUSTOM_ENGINE_ACTION_START;
+		event.customType = evtType;
+	}
+
 	void setKeyEvent(const KeyState &ks) {
 		event = Event();
 		event.type = EVENT_KEYDOWN;
diff --git a/backends/keymapper/keymap.cpp b/backends/keymapper/keymap.cpp
index 38b70e8..917d3ec 100644
--- a/backends/keymapper/keymap.cpp
+++ b/backends/keymapper/keymap.cpp
@@ -136,6 +136,13 @@ void Keymap::registerBackendDefaultMappings() {
 
 		if (!defaultHwId.empty()) {
 			action->addDefaultInputMapping(defaultHwId);
+			continue;
+		}
+
+		// If no keymap-specific default mapping was found, look for a standard action binding
+		defaultHwId = _backendDefaultBindings->getDefaultBinding(kStandardActionsKeymapName, action->id);
+		if (!defaultHwId.empty()) {
+			action->addDefaultInputMapping(defaultHwId);
 		}
 	}
 }
diff --git a/backends/keymapper/keymap.h b/backends/keymapper/keymap.h
index dae35f1..1cdc538 100644
--- a/backends/keymapper/keymap.h
+++ b/backends/keymapper/keymap.h
@@ -33,6 +33,8 @@
 
 namespace Common {
 
+const char *const kStandardActionsKeymapName = "standard-actions";
+
 class Action;
 struct HardwareInput;
 class HardwareInputSet;
diff --git a/backends/keymapper/keymapper.cpp b/backends/keymapper/keymapper.cpp
index e4b580e..ce39980 100644
--- a/backends/keymapper/keymapper.cpp
+++ b/backends/keymapper/keymapper.cpp
@@ -180,6 +180,13 @@ List<Event> Keymapper::mapEvent(const Event &ev) {
 		}
 	}
 
+	// Ignore keyboard repeat events. Repeat event are meant for text input,
+	// the keymapper / keymaps are supposed to be disabled during text input.
+	// TODO: Add a way to keep repeat events if needed.
+	if (!mappedEvents.empty() && ev.type == EVENT_KEYDOWN && ev.kbdRepeat) {
+		return List<Event>();
+	}
+
 	if (mappedEvents.empty()) {
 		// if it didn't get mapped, just pass it through
 		mappedEvents.push_back(ev);
@@ -245,6 +252,9 @@ EventType Keymapper::convertStartToEnd(EventType type) {
 	case EVENT_CUSTOM_BACKEND_ACTION_START:
 		result = EVENT_CUSTOM_BACKEND_ACTION_END;
 		break;
+	case EVENT_CUSTOM_ENGINE_ACTION_START:
+		result = EVENT_CUSTOM_ENGINE_ACTION_END;
+		break;
 	default:
 		break;
 	}
diff --git a/backends/keymapper/standard-actions.cpp b/backends/keymapper/standard-actions.cpp
new file mode 100644
index 0000000..03e072c
--- /dev/null
+++ b/backends/keymapper/standard-actions.cpp
@@ -0,0 +1,38 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "backends/keymapper/standard-actions.h"
+
+namespace Common {
+
+const char *kStandardActionSkip          = "SKIP";
+const char *kStandardActionPause         = "PAUSE";
+const char *kStandardActionMoveForward   = "FWD";
+const char *kStandardActionMoveBackwards = "BWD";
+const char *kStandardActionTurnLeft      = "TL";
+const char *kStandardActionTurnRight     = "TR";
+const char *kStandardActionMoveUpwards   = "UP";
+const char *kStandardActionMoveDownwards = "DOWN";
+const char *kStandardActionOpenDebugger  = "DBG";
+const char *kStandardActionOpenMainMenu  = "MENU";
+
+} //namespace Common
diff --git a/backends/keymapper/standard-actions.h b/backends/keymapper/standard-actions.h
new file mode 100644
index 0000000..b866289
--- /dev/null
+++ b/backends/keymapper/standard-actions.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BACKENDS_KEYMAPPER_STANDARD_ACTIONS_H
+#define BACKENDS_KEYMAPPER_STANDARD_ACTIONS_H
+
+/**
+ * @file
+ * @brief A set of well known keymapper actions.
+ *
+ * The actions in this file are meant to be used by game engines
+ * when defining their key mappings.
+ * Backends can provide default key mappings for some of these actions
+ * so users don't have to manually configure the action mappings for
+ * the input devices.
+ */
+
+namespace Common {
+
+extern const char *kStandardActionSkip;
+extern const char *kStandardActionPause;
+extern const char *kStandardActionMoveForward;
+extern const char *kStandardActionMoveBackwards;
+extern const char *kStandardActionTurnLeft;
+extern const char *kStandardActionTurnRight;
+extern const char *kStandardActionMoveUpwards;
+extern const char *kStandardActionMoveDownwards;
+extern const char *kStandardActionOpenDebugger;
+extern const char *kStandardActionOpenMainMenu;
+
+} //namespace Common
+
+#endif // BACKENDS_KEYMAPPER_STANDARD_ACTIONS_H
diff --git a/backends/module.mk b/backends/module.mk
index f62c1e2..155503d 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -14,6 +14,7 @@ MODULE_OBJS := \
 	keymapper/keymap.o \
 	keymapper/keymapper.o \
 	keymapper/remap-widget.o \
+	keymapper/standard-actions.o \
 	log/log.o \
 	midi/alsa.o \
 	midi/dmedia.o \
diff --git a/backends/platform/maemo/maemo.cpp b/backends/platform/maemo/maemo.cpp
index 38f36cd..b2e4990 100644
--- a/backends/platform/maemo/maemo.cpp
+++ b/backends/platform/maemo/maemo.cpp
@@ -196,10 +196,7 @@ Common::KeymapArray OSystem_SDL_Maemo::getGlobalKeymaps() {
 	Action *act;
 
 	act = new Action("CLKM", _("Click Mode"));
-	Event evt = Event();
-	evt.type = EVENT_CUSTOM_BACKEND_ACTION_START;
-	evt.customType = Maemo::kEventClickMode;
-	act->setEvent(evt);
+	act->setCustomBackendActionEvent(Maemo::kEventClickMode);
 	globalMap->addAction(act);
 
 	act = new Action("LCLK", _("Left Click"));
diff --git a/common/EventDispatcher.cpp b/common/EventDispatcher.cpp
index ccfc40f..7b0d754 100644
--- a/common/EventDispatcher.cpp
+++ b/common/EventDispatcher.cpp
@@ -60,6 +60,9 @@ void EventDispatcher::dispatch() {
 				// to be the output of the event mapper.
 				assert(event.type != EVENT_CUSTOM_BACKEND_ACTION_START);
 				assert(event.type != EVENT_CUSTOM_BACKEND_ACTION_END);
+				assert(event.type != EVENT_CUSTOM_ENGINE_ACTION_START);
+				assert(event.type != EVENT_CUSTOM_ENGINE_ACTION_END);
+
 
 				List<Event> mappedEvents = _mapper->mapEvent(event);
 
diff --git a/common/events.h b/common/events.h
index ddb32ca..3e4d046 100644
--- a/common/events.h
+++ b/common/events.h
@@ -75,11 +75,12 @@ enum EventType {
 	EVENT_PREDICTIVE_DIALOG = 12,
 
 	EVENT_CUSTOM_BACKEND_ACTION_START = 18,
-	EVENT_CUSTOM_BACKEND_ACTION_END = 19,
-	EVENT_CUSTOM_BACKEND_HARDWARE = 21,
+	EVENT_CUSTOM_BACKEND_ACTION_END   = 19,
+	EVENT_CUSTOM_ENGINE_ACTION_START  = 20,
+	EVENT_CUSTOM_ENGINE_ACTION_END    = 21,
 
 #ifdef ENABLE_VKEYBD
-	EVENT_VIRTUAL_KEYBOARD = 20,
+	EVENT_VIRTUAL_KEYBOARD = 22,
 #endif
 
 	EVENT_DROP_FILE = 23,
@@ -88,7 +89,9 @@ enum EventType {
 	EVENT_JOYBUTTON_DOWN = 25,
 	EVENT_JOYBUTTON_UP = 26,
 
-	EVENT_CLIPBOARD_UPDATE = 27
+	EVENT_CLIPBOARD_UPDATE = 27,
+
+	EVENT_CUSTOM_BACKEND_HARDWARE = 28
 };
 
 const int16 JOYAXIS_MIN = -32768;


Commit: 0995f40677521268476785c617ff97b5b46c2413
    https://github.com/scummvm/scummvm/commit/0995f40677521268476785c617ff97b5b46c2413
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
MOHAWK: RIVEN: Use custom engine actions for event handing

Changed paths:
  A engines/mohawk/riven_actions.h
    backends/keymapper/standard-actions.cpp
    backends/keymapper/standard-actions.h
    engines/mohawk/riven.cpp
    engines/mohawk/riven_card.cpp
    engines/mohawk/riven_card.h
    engines/mohawk/riven_stack.cpp
    engines/mohawk/riven_stack.h
    engines/mohawk/riven_stacks/jspit.cpp
    engines/mohawk/riven_video.cpp


diff --git a/backends/keymapper/standard-actions.cpp b/backends/keymapper/standard-actions.cpp
index 03e072c..006a8e5 100644
--- a/backends/keymapper/standard-actions.cpp
+++ b/backends/keymapper/standard-actions.cpp
@@ -24,6 +24,7 @@
 
 namespace Common {
 
+const char *kStandardActionInteract      = "INTCT";
 const char *kStandardActionSkip          = "SKIP";
 const char *kStandardActionPause         = "PAUSE";
 const char *kStandardActionMoveForward   = "FWD";
diff --git a/backends/keymapper/standard-actions.h b/backends/keymapper/standard-actions.h
index b866289..bcf78a6 100644
--- a/backends/keymapper/standard-actions.h
+++ b/backends/keymapper/standard-actions.h
@@ -36,6 +36,7 @@
 
 namespace Common {
 
+extern const char *kStandardActionInteract;
 extern const char *kStandardActionSkip;
 extern const char *kStandardActionPause;
 extern const char *kStandardActionMoveForward;
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index 5c436bf..a64515c 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -29,6 +29,7 @@
 #include "common/system.h"
 #include "backends/keymapper/action.h"
 #include "backends/keymapper/keymapper.h"
+#include "backends/keymapper/standard-actions.h"
 #include "graphics/scaler.h"
 #include "gui/saveload.h"
 #include "gui/message.h"
@@ -221,7 +222,7 @@ void MohawkEngine_Riven::doFrame() {
 	_video->updateMovies();
 
 	if (!_scriptMan->hasQueuedScripts()) {
-		_stack->keyResetAction();
+		_stack->resetAction();
 	}
 
 	processInput();
@@ -263,70 +264,67 @@ void MohawkEngine_Riven::processInput() {
 			_stack->onMouseUp(_eventMan->getMousePos());
 			_inventory->checkClick(_eventMan->getMousePos());
 			break;
-		case Common::EVENT_KEYUP:
-			_stack->keyResetAction();
+		case Common::EVENT_CUSTOM_ENGINE_ACTION_END:
+			switch ((RivenAction)event.customType) {
+			case kRivenActionInteract:
+				_stack->onMouseUp(_eventMan->getMousePos());
+				_inventory->checkClick(_eventMan->getMousePos());
+				break;
+			default:
+				_stack->resetAction();
+				break;
+			}
 			break;
-		case Common::EVENT_KEYDOWN:
-			switch (event.kbd.keycode) {
-			case Common::KEYCODE_d:
-				if (event.kbd.flags & Common::KBD_CTRL) {
-					_console->attach();
-					_console->onFrame();
-				}
+		case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
+			switch ((RivenAction)event.customType) {
+			case kRivenActionInteract:
+				_stack->onMouseDown(_eventMan->getMousePos());
 				break;
-			case Common::KEYCODE_SPACE:
+			case kRivenActionOpenDebugger:
+				_console->attach();
+				_console->onFrame();
+				break;
+			case kRivenActionPause:
 				pauseGame();
 				break;
-			case Common::KEYCODE_F5:
+			case kRivenActionOpenOptionsDialog:
 				runOptionsDialog();
 				break;
-			case Common::KEYCODE_r:
-				// Return to the main menu in the demo on ctrl+r
-				if (event.kbd.flags & Common::KBD_CTRL && getFeatures() & GF_DEMO) {
+			case kRivenActionOpenMainMenu:
+				if (getFeatures() & GF_DEMO) {
+					// Return to the main menu in the demo
 					if (_stack->getId() != kStackAspit)
 						changeToStack(kStackAspit);
 					changeToCard(1);
+				} else if (!_scriptMan->hasQueuedScripts() && getFeatures() & GF_25TH) {
+					// Check if we haven't jumped to menu
+					if (_menuSavedStack == -1) {
+						goToMainMenu();
+					} else {
+						resumeFromMainMenu();
+					}
 				}
 				break;
-			case Common::KEYCODE_p:
-				// Play the intro videos in the demo on ctrl+p
-				if (event.kbd.flags & Common::KBD_CTRL && getFeatures() & GF_DEMO) {
+			case kRivenActionPlayIntroVideos:
+				// Play the intro videos in the demo
+				if (getFeatures() & GF_DEMO) {
 					if (_stack->getId() != kStackAspit)
 						changeToStack(kStackAspit);
 					changeToCard(6);
 				}
 				break;
-			case Common::KEYCODE_o:
-				if (event.kbd.flags & Common::KBD_CTRL) {
-					if (canLoadGameStateCurrently()) {
-						runLoadDialog();
-					}
+			case kRivenActionLoadGameState:
+				if (canLoadGameStateCurrently()) {
+					runLoadDialog();
 				}
 				break;
-			case Common::KEYCODE_s:
-				if (event.kbd.flags & Common::KBD_CTRL) {
-					if (canSaveGameStateCurrently()) {
-						runSaveDialog();
-					}
-				}
-				break;
-			case Common::KEYCODE_ESCAPE:
-				if (!_scriptMan->hasQueuedScripts() && getFeatures() & GF_25TH) {
-					// Check if we haven't jumped to menu
-					if (_menuSavedStack == -1) {
-						goToMainMenu();
-					} else {
-						resumeFromMainMenu();
-					}
-				} else {
-					_stack->onKeyPressed(event.kbd);
+			case kRivenActionSaveGameState:
+				if (canSaveGameStateCurrently()) {
+					runSaveDialog();
 				}
 				break;
 			default:
-				if (event.kbdRepeat) {
-					continue;
-				}
-				_stack->onKeyPressed(event.kbd);
+				_stack->onAction((RivenAction)event.customType);
 				break;
 			}
 			break;
@@ -875,54 +873,63 @@ void MohawkEngine_Riven::runOptionsDialog() {
 }
 
 Common::Keymap *MohawkEngine_Riven::initKeymap(const char *target) {
-	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, "riven");
-
-	const Common::KeyActionEntry keyActionEntries[] = {
-		{ "UP",   Common::KEYCODE_UP,                                         "UP",       _("Move Forward")           },
-		{ "DWN",  Common::KEYCODE_DOWN,                                       "DOWN",     _("Move Back")              },
-		{ "TL",   Common::KEYCODE_LEFT,                                       "LEFT",     _("Turn Left")              },
-		{ "TR",   Common::KEYCODE_RIGHT,                                      "RIGHT",    _("Turn Right")             },
-		{ "LKUP", Common::KEYCODE_PAGEUP,                                     "PAGEUP",   _("Look Up")                },
-		{ "LKDN", Common::KEYCODE_PAGEDOWN,                                   "PAGEDOWN", _("Look Down")              },
-		{ "OPTS", Common::KEYCODE_F5,                                         "F5",       _("Show/Hide Options Menu") },
-		{ "PAUS", Common::KEYCODE_SPACE,                                      "SPACE",    _("Pause")                  },
-		{ "LOAD", Common::KeyState(Common::KEYCODE_o, 'o', Common::KBD_CTRL), "C+o",      _("Load Game State")        },
-		{ "SAVE", Common::KeyState(Common::KEYCODE_s, 's', Common::KBD_CTRL), "C+s",      _("Save Game State")        }
+	using namespace Common;
+
+	Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "riven");
+
+	if (checkGameGUIOption(GAMEOPTION_25TH, ConfMan.get("guioptions", target))) {
+		Action* const act = new Action(kStandardActionOpenMainMenu, _("Open main menu"));
+		act->setCustomEngineActionEvent(kRivenActionOpenMainMenu);
+		act->addDefaultInputMapping("ESCAPE");
+		engineKeyMap->addAction(act);
+	}
+
+	struct ActionEntry {
+		const char *id;
+		const RivenAction action;
+		const char *defaultHwId;
+		const char *description;
 	};
 
-	const Common::KeyActionEntry keyActionEntriesDemo[] = {
-		{ "RMM",  Common::KeyState(Common::KEYCODE_r, 'r', Common::KBD_CTRL), "C+r",      _("Return To Main Menu")    },
-		{ "INTV", Common::KeyState(Common::KEYCODE_p, 'p', Common::KBD_CTRL), "C+p",      _("Play Intro Videos")      }
+	const ActionEntry keyActionEntries[] = {
+		{ kStandardActionSkip,          kRivenActionSkip,              "ESCAPE",   _("Skip")                },
+		{ kStandardActionInteract,      kRivenActionInteract,          "RETURN",   _("Interact")            },
+		{ "LOAD",                       kRivenActionLoadGameState,     "C+o",      _("Load game state")     },
+		{ "SAVE",                       kRivenActionSaveGameState,     "C+s",      _("Save game state")     },
+		{ "OPTS",                       kRivenActionOpenOptionsDialog, "F5",       _("Show options menu")   },
+		{ kStandardActionPause,         kRivenActionPause,             "SPACE",    _("Pause")               },
+		{ kStandardActionMoveForward,   kRivenActionMoveForward,       "UP",       _("Move forward")        },
+		{ "FWDL",                       kRivenActionMoveForwardLeft,   "",         _("Move forward left")   },
+		{ "FWDR",                       kRivenActionMoveForwardRight,  "",         _("Move forward right")  },
+		{ kStandardActionMoveBackwards, kRivenActionMoveBack,          "DOWN",     _("Move backwards")      },
+		{ kStandardActionTurnLeft,      kRivenActionMoveLeft,          "LEFT",     _("Turn left")           },
+		{ kStandardActionTurnRight,     kRivenActionMoveRight,         "RIGHT",    _("Turn right")          },
+		{ kStandardActionMoveUpwards,   kRivenActionLookUp,            "PAGEUP",   _("Look up")             },
+		{ kStandardActionMoveDownwards, kRivenActionLookDown,          "PAGEDOWN", _("Look down")           },
+		{ kStandardActionOpenDebugger,  kRivenActionOpenDebugger,      "C+d",      _("Open debugger")       }
+	};
+
+	const ActionEntry keyActionEntriesDemo[] = {
+		{ kStandardActionOpenMainMenu,  kRivenActionOpenMainMenu,      "C+r",      _("Return to main menu") },
+		{ "INTV",                       kRivenActionPlayIntroVideos,   "C+p",      _("Play intro videos")   }
 	};
 
 	for (uint i = 0; i < ARRAYSIZE(keyActionEntries); i++) {
-		Common::Action *const act = new Common::Action(keyActionEntries[i].id, keyActionEntries[i].description);
-		act->setKeyEvent(keyActionEntries[i].ks);
+		Action *act = new Action(keyActionEntries[i].id, keyActionEntries[i].description);
+		act->setCustomEngineActionEvent(keyActionEntries[i].action);
 		act->addDefaultInputMapping(keyActionEntries[i].defaultHwId);
 		engineKeyMap->addAction(act);
 	}
 
-	if (Common::checkGameGUIOption(GAMEOPTION_DEMO, ConfMan.get("guioptions", target))) {
+	if (checkGameGUIOption(GAMEOPTION_DEMO, ConfMan.get("guioptions", target))) {
 		for (uint i = 0; i < ARRAYSIZE(keyActionEntriesDemo); i++) {
-			Common::Action* const act = new Common::Action(keyActionEntriesDemo[i].id, keyActionEntriesDemo[i].description);
-			act->setKeyEvent(keyActionEntriesDemo[i].ks);
+			Action *act = new Action(keyActionEntriesDemo[i].id, keyActionEntriesDemo[i].description);
+			act->setCustomEngineActionEvent(keyActionEntriesDemo[i].action);
 			act->addDefaultInputMapping(keyActionEntriesDemo[i].defaultHwId);
 			engineKeyMap->addAction(act);
 		}
 	}
 
-	if (Common::checkGameGUIOption(GAMEOPTION_25TH, ConfMan.get("guioptions", target))) {
-		Common::Action* const act = new Common::Action("SMNU", _("Skip / Open main menu"));
-		act->setKeyEvent(Common::KEYCODE_ESCAPE);
-		act->addDefaultInputMapping("ESCAPE");
-		engineKeyMap->addAction(act);
-	} else {
-		Common::Action* const act = new Common::Action("SKIP", _("Skip"));
-		act->setKeyEvent(Common::KEYCODE_ESCAPE);
-		act->addDefaultInputMapping("ESCAPE");
-		engineKeyMap->addAction(act);
-	}
-
 	return engineKeyMap;
 }
 
diff --git a/engines/mohawk/riven_actions.h b/engines/mohawk/riven_actions.h
new file mode 100644
index 0000000..bc29d87
--- /dev/null
+++ b/engines/mohawk/riven_actions.h
@@ -0,0 +1,52 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef MOHAWK_RIVEN_ACTIONS_H
+#define MOHAWK_RIVEN_ACTIONS_H
+
+namespace Mohawk {
+
+/** Actions that can be performed using the keyboard */
+enum RivenAction {
+	kRivenActionNone,
+	kRivenActionInteract,
+	kRivenActionSkip,
+	kRivenActionMoveForward,
+	kRivenActionMoveForwardLeft,
+	kRivenActionMoveForwardRight,
+	kRivenActionMoveLeft,
+	kRivenActionMoveRight,
+	kRivenActionMoveBack,
+	kRivenActionLookUp,
+	kRivenActionLookDown,
+	kRivenActionOpenMainMenu,
+	kRivenActionPause,
+	kRivenActionPlayIntroVideos,
+	kRivenActionLoadGameState,
+	kRivenActionSaveGameState,
+	kRivenActionOpenOptionsDialog,
+	kRivenActionOpenDebugger
+};
+
+} // End of namespace Mohawk
+
+#endif // MOHAWK_RIVEN_ACTIONS_H
diff --git a/engines/mohawk/riven_card.cpp b/engines/mohawk/riven_card.cpp
index db83305..67d32c6 100644
--- a/engines/mohawk/riven_card.cpp
+++ b/engines/mohawk/riven_card.cpp
@@ -1068,7 +1068,7 @@ void RivenCard::playMovie(uint16 index, bool queue) {
 	}
 }
 
-RivenScriptPtr RivenCard::onKeyAction(RivenKeyAction keyAction) {
+RivenScriptPtr RivenCard::onKeyAction(RivenAction keyAction) {
 	static const char *forwardNames[] = {
 			"forward", "forward1", "forward2", "forward3",
 			"opendoor", "openhatch", "opentrap", "opengate", "opengrate",
@@ -1086,28 +1086,28 @@ RivenScriptPtr RivenCard::onKeyAction(RivenKeyAction keyAction) {
 
 	const char **hotspotNames = nullptr;
 	switch (keyAction) {
-		case kKeyActionMoveForward:
+		case kRivenActionMoveForward:
 			hotspotNames = forwardNames;
 			break;
-		case kKeyActionMoveForwardLeft:
+		case kRivenActionMoveForwardLeft:
 			hotspotNames = forwardLeftNames;
 			break;
-		case kKeyActionMoveForwardRight:
+		case kRivenActionMoveForwardRight:
 			hotspotNames = forwardRightNames;
 			break;
-		case kKeyActionMoveLeft:
+		case kRivenActionMoveLeft:
 			hotspotNames = leftNames;
 			break;
-		case kKeyActionMoveRight:
+		case kRivenActionMoveRight:
 			hotspotNames = rightNames;
 			break;
-		case kKeyActionMoveBack:
+		case kRivenActionMoveBack:
 			hotspotNames = backNames;
 			break;
-		case kKeyActionLookUp:
+		case kRivenActionLookUp:
 			hotspotNames = upNames;
 			break;
-		case kKeyActionLookDown:
+		case kRivenActionLookDown:
 			hotspotNames = downNames;
 			break;
 		default:
diff --git a/engines/mohawk/riven_card.h b/engines/mohawk/riven_card.h
index c092f59..53085c8 100644
--- a/engines/mohawk/riven_card.h
+++ b/engines/mohawk/riven_card.h
@@ -129,7 +129,7 @@ public:
 	RivenScriptPtr onMouseMove(const Common::Point &mouse);
 
 	/** Handle a keyboard action */
-	RivenScriptPtr onKeyAction(RivenKeyAction keyAction);
+	RivenScriptPtr onKeyAction(RivenAction keyAction);
 
 	/** General frame update handler */
 	RivenScriptPtr onFrame();
diff --git a/engines/mohawk/riven_stack.cpp b/engines/mohawk/riven_stack.cpp
index c0a7587..951fab1 100644
--- a/engines/mohawk/riven_stack.cpp
+++ b/engines/mohawk/riven_stack.cpp
@@ -41,7 +41,7 @@ RivenStack::RivenStack(MohawkEngine_Riven *vm, uint16 id) :
 		_id(id),
 		_mouseIsDown(false),
 		_shouldRefreshMouseCursor(false),
-		_keyAction(kKeyActionNone) {
+		_action(kRivenActionNone) {
 	removeTimer();
 
 	loadResourceNames();
@@ -351,19 +351,19 @@ void RivenStack::onFrame() {
 	_vm->_scriptMan->runScript(script, true);
 }
 
-RivenKeyAction RivenStack::keyGetAction() const {
-	return _keyAction;
+RivenAction RivenStack::getAction() const {
+	return _action;
 }
 
-void RivenStack::keyResetAction() {
-	_keyAction = kKeyActionNone;
+void RivenStack::resetAction() {
+	_action = kRivenActionNone;
 }
 
-void RivenStack::onKeyPressed(const Common::KeyState &keyState) {
-	_keyAction = mapKeyStateToKeyAction(keyState);
+void RivenStack::onAction(RivenAction action) {
+	_action = action;
 
 	if (_vm->getCard() && !_vm->_scriptMan->hasQueuedScripts()) {
-		RivenScriptPtr script = _vm->getCard()->onKeyAction(_keyAction);
+		RivenScriptPtr script = _vm->getCard()->onKeyAction(_action);
 
 		if (!script->empty()) {
 			_vm->_scriptMan->runScript(script, true);
@@ -371,59 +371,6 @@ void RivenStack::onKeyPressed(const Common::KeyState &keyState) {
 	}
 }
 
-RivenKeyAction RivenStack::mapKeyStateToKeyAction(const Common::KeyState &keyState) {
-	switch (keyState.keycode) {
-		case Common::KEYCODE_ESCAPE:
-			return kKeyActionSkip;
-		case Common::KEYCODE_KP8:
-			if (keyState.flags & Common::KBD_NUM) {
-				break;
-			}
-			// Fallthrough
-		case Common::KEYCODE_UP:
-			return kKeyActionMoveForward;
-		case Common::KEYCODE_KP7:
-			if (keyState.flags & Common::KBD_NUM) {
-				break;
-			}
-			return kKeyActionMoveForwardLeft;
-		case Common::KEYCODE_KP9:
-			if (keyState.flags & Common::KBD_NUM) {
-				break;
-			}
-			return kKeyActionMoveForwardRight;
-		case Common::KEYCODE_KP4:
-			if (keyState.flags & Common::KBD_NUM) {
-				break;
-			}
-			// Fallthrough
-		case Common::KEYCODE_LEFT:
-			return kKeyActionMoveLeft;
-		case Common::KEYCODE_KP6:
-			if (keyState.flags & Common::KBD_NUM) {
-				break;
-			}
-			// Fallthrough
-		case Common::KEYCODE_RIGHT:
-			return kKeyActionMoveRight;
-		case Common::KEYCODE_KP2:
-			if (keyState.flags & Common::KBD_NUM) {
-				break;
-			}
-			// Fallthrough
-		case Common::KEYCODE_DOWN:
-			return kKeyActionMoveBack;
-		case Common::KEYCODE_PAGEUP:
-			return kKeyActionLookUp;
-		case Common::KEYCODE_PAGEDOWN:
-			return kKeyActionLookDown;
-		default:
-			break;
-	}
-
-	return kKeyActionNone;
-}
-
 Common::Point RivenStack::getMousePosition() const {
 	return _mousePosition;
 }
@@ -474,7 +421,7 @@ void RivenStack::pageTurn(RivenTransition transition) {
 }
 
 bool RivenStack::keepTurningPages() {
-	return (mouseIsDown() || keyGetAction() != kKeyActionNone) && !_vm->shouldQuit();
+	return (mouseIsDown() || getAction() != kRivenActionNone) && !_vm->shouldQuit();
 }
 
 void RivenStack::waitForPageTurnSound() {
diff --git a/engines/mohawk/riven_stack.h b/engines/mohawk/riven_stack.h
index aba6cc9..e58c001 100644
--- a/engines/mohawk/riven_stack.h
+++ b/engines/mohawk/riven_stack.h
@@ -29,6 +29,7 @@
 #include "common/rect.h"
 #include "common/str-array.h"
 
+#include "mohawk/riven_actions.h"
 #include "mohawk/riven_graphics.h"
 
 namespace Mohawk {
@@ -78,20 +79,6 @@ private:
 	Common::Array<uint16> _index;
 };
 
-/** Actions that can be performed using the keyboard */
-enum RivenKeyAction {
-	kKeyActionNone,
-	kKeyActionSkip,
-	kKeyActionMoveForward,
-	kKeyActionMoveForwardLeft,
-	kKeyActionMoveForwardRight,
-	kKeyActionMoveLeft,
-	kKeyActionMoveRight,
-	kKeyActionMoveBack,
-	kKeyActionLookUp,
-	kKeyActionLookDown
-};
-
 /**
  * A game level
  *
@@ -177,13 +164,13 @@ public:
 	void mouseForceUp();
 
 	/** Handle a key press event */
-	void onKeyPressed(const Common::KeyState &keyState);
+	void onAction(RivenAction keyAction);
 
 	/** Get the action for the pressed keyboard key, if any */
-	RivenKeyAction keyGetAction() const;
+	RivenAction getAction() const;
 
 	/** Force the keyboard to be considered unpressed until the next key press */
-	void keyResetAction();
+	void resetAction();
 
 	// Common external commands
 	void xflies(const ArgumentArray &args); // Start the "flies" effect
@@ -238,8 +225,7 @@ private:
 
 	CommandsMap _commands;
 
-	RivenKeyAction _keyAction;
-	RivenKeyAction mapKeyStateToKeyAction(const Common::KeyState &keyState);
+	RivenAction _action;
 
 	bool _mouseIsDown;
 	Common::Point _mousePosition;
diff --git a/engines/mohawk/riven_stacks/jspit.cpp b/engines/mohawk/riven_stacks/jspit.cpp
index b1f15a1..e8c133c 100644
--- a/engines/mohawk/riven_stacks/jspit.cpp
+++ b/engines/mohawk/riven_stacks/jspit.cpp
@@ -552,7 +552,7 @@ void JSpit::sunnersPlayVideo(RivenVideo *video, uint32 destCardGlobalId, bool su
 	while (!video->endOfVideo() && !_vm->hasGameEnded()) {
 		_vm->doFrame();
 
-		if (mouseIsDown() || keyGetAction() == kKeyActionMoveForward) {
+		if (mouseIsDown() || getAction() == kRivenActionMoveForward) {
 			video->stop();
 
 			if (sunnersShouldFlee) {
diff --git a/engines/mohawk/riven_video.cpp b/engines/mohawk/riven_video.cpp
index 745f96b..38d7e7f 100644
--- a/engines/mohawk/riven_video.cpp
+++ b/engines/mohawk/riven_video.cpp
@@ -241,14 +241,14 @@ void RivenVideo::playBlocking(int32 endTime) {
 		_vm->doFrame();
 
 		// Handle skipping
-		if (playTillEnd && _vm->getStack()->keyGetAction() == kKeyActionSkip) {
+		if (playTillEnd && _vm->getStack()->getAction() == kRivenActionSkip) {
 			continuePlaying = false;
 
 			// Seek to the last frame
 			_video->seek(_video->getDuration().addMsecs(-1));
 
 			_vm->getStack()->mouseForceUp();
-			_vm->getStack()->keyResetAction();
+			_vm->getStack()->resetAction();
 		}
 	}
 


Commit: df7ce0c55f6802093b2d11d46dc96e34d1a0ee05
    https://github.com/scummvm/scummvm/commit/df7ce0c55f6802093b2d11d46dc96e34d1a0ee05
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
KEYMAPPER: Rework HardwareInputSet not to allocate all possible inputs

Changed paths:
    backends/keymapper/action.h
    backends/keymapper/hardware-input.cpp
    backends/keymapper/hardware-input.h
    backends/keymapper/input-watcher.cpp
    backends/keymapper/input-watcher.h
    backends/keymapper/keymap.cpp
    backends/keymapper/keymap.h
    backends/keymapper/keymapper.cpp
    backends/keymapper/keymapper.h
    backends/keymapper/remap-widget.cpp
    backends/platform/linuxmoto/hardwarekeys.cpp
    backends/platform/maemo/maemo.cpp


diff --git a/backends/keymapper/action.h b/backends/keymapper/action.h
index 11e4b82..0e35d80 100644
--- a/backends/keymapper/action.h
+++ b/backends/keymapper/action.h
@@ -51,7 +51,7 @@ private:
 	Array<String> _defaultInputMapping;
 
 public:
-	Action(const char *id, const String &description = "");
+	Action(const char *id, const String &description);
 
 	void setEvent(const Event &evt) {
 		event = evt;
diff --git a/backends/keymapper/hardware-input.cpp b/backends/keymapper/hardware-input.cpp
index 91d5b3c..42041b1 100644
--- a/backends/keymapper/hardware-input.cpp
+++ b/backends/keymapper/hardware-input.cpp
@@ -23,10 +23,11 @@
 #include "backends/keymapper/hardware-input.h"
 
 #include "backends/keymapper/keymapper.h"
+#include "common/tokenizer.h"
 
 namespace Common {
 
-static const KeyTableEntry defaultKeys[] = {
+const KeyTableEntry defaultKeys[] = {
 	{"BACKSPACE", KEYCODE_BACKSPACE, "Backspace"},
 	{"TAB", KEYCODE_TAB, "Tab"},
 	{"CLEAR", KEYCODE_CLEAR, "Clear"},
@@ -205,100 +206,175 @@ static const KeyTableEntry defaultKeys[] = {
 	{0, KEYCODE_INVALID, 0}
 };
 
-// TODO: Add META and NUM_LOCK
-static const ModifierTableEntry defaultModifiers[] = {
-	{ 0, "", "" },
-	{ KBD_CTRL, "C+", "Ctrl+" },
-	{ KBD_ALT, "A+", "Alt+" },
-	{ KBD_SHIFT, "S+", "Shift+" },
-	{ KBD_CTRL | KBD_ALT, "C+A+", "Ctrl+Alt+" },
-	{ KBD_SHIFT | KBD_CTRL, "S+C+", "Shift+Ctrl+" },
-	{ KBD_SHIFT | KBD_CTRL | KBD_ALT, "S+C+A+", "Shift+Ctrl+Alt+" },
-	{ 0, 0, 0 }
+// TODO: Add NUM_LOCK
+const ModifierTableEntry defaultModifiers[] = {
+	{ KBD_CTRL,  "C", "Ctrl+"  },
+	{ KBD_SHIFT, "S", "Shift+" },
+	{ KBD_ALT,   "A", "Alt+"   },
+	{ KBD_META,  "M", "Meta+"  },
+	{ 0,     nullptr, nullptr }
 };
 
-HardwareInputSet::HardwareInputSet(bool useDefault, const KeyTableEntry *keys, const ModifierTableEntry *modifiers) {
-	if (useDefault)
-		addHardwareInputs(defaultKeys, defaultModifiers);
-	if (keys)
-		addHardwareInputs(keys, modifiers ? modifiers : defaultModifiers);
+HardwareInputSet::~HardwareInputSet() {
 }
 
-HardwareInputSet::~HardwareInputSet() {
-	for (KeyInputMap::iterator it = _keyInput.begin(); it != _keyInput.end(); ++it)
-		delete it->_value;
-	for (CustomInputMap::iterator it = _customInput.begin(); it != _customInput.end(); ++it)
-		delete it->_value;
+KeyboardHardwareInputSet::KeyboardHardwareInputSet(const KeyTableEntry *keys, const ModifierTableEntry *modifiers) :
+		_keys(keys),
+		_modifiers(modifiers) {
+	assert(_keys);
+	assert(_modifiers);
 }
 
-const HardwareInput *HardwareInputSet::findHardwareInput(const String &id) const {
-	for (KeyInputMap::const_iterator it = _keyInput.begin(); it != _keyInput.end(); ++it) {
-		if ((*it)._value->id == id)
-			return (*it)._value;
+HardwareInput KeyboardHardwareInputSet::findHardwareInput(const String &id) const {
+	StringTokenizer tokenizer(id, "+");
+
+	byte modifierFlags = 0;
+
+	// TODO: Normalize modifier order
+	String fullKeyDesc;
+
+	String token;
+	while (!tokenizer.empty()) {
+		token = tokenizer.nextToken();
+
+		const ModifierTableEntry *modifier = nullptr;
+		for (modifier = _modifiers;  modifier->id; modifier++) {
+			if (token == modifier->id) {
+				break;
+			}
+		}
+
+		if (modifier && modifier->id) {
+			modifierFlags |= modifier->flag;
+			fullKeyDesc += modifier->desc;
+		} else {
+			// We reached the end of the modifiers, the token is a keycode
+			break;
+		}
 	}
-	for (CustomInputMap::const_iterator it = _customInput.begin(); it != _customInput.end(); ++it) {
-		if ((*it)._value->id == id)
-			return (*it)._value;
+
+	if (!tokenizer.empty()) {
+		return HardwareInput();
 	}
 
-	return nullptr;
-}
+	const KeyTableEntry *key = nullptr;
+	for (key = _keys;  key->hwId; key++) {
+		if (token.equals(key->hwId)) {
+			break;
+		}
+	}
 
-const HardwareInput *HardwareInputSet::findHardwareInput(const HardwareInputCode code) const {
-	return _customInput[code];
-}
+	if (!key || !key->hwId) {
+		return HardwareInput();
+	}
 
-const HardwareInput *HardwareInputSet::findHardwareInput(const KeyState &keystate) const {
-	return _keyInput[keystate];
+	const KeyState keystate = KeyState(key->keycode, 0, modifierFlags);
+	return HardwareInput(id, keystate, fullKeyDesc + key->desc);
 }
 
-void HardwareInputSet::addHardwareInputs(const HardwareInputTableEntry inputs[]) {
-	for (const HardwareInputTableEntry *entry = inputs; entry->hwId; ++entry) {
-		const HardwareInput *existingInput = findHardwareInput(entry->code);
-		if (existingInput) {
-			warning("Ignoring hardware input %s (code %d) because an input with the same code is already defined",
-			        entry->desc, entry->code);
-			continue;
+HardwareInput KeyboardHardwareInputSet::findHardwareInput(const Event &event) const {
+	switch (event.type) {
+	case EVENT_KEYDOWN:
+	case EVENT_KEYUP: {
+		const KeyTableEntry *key = nullptr;
+		for (key = _keys;  key->hwId; key++) {
+			if (event.kbd.keycode == key->keycode) {
+				break;
+			}
 		}
 
-		existingInput = findHardwareInput(entry->hwId);
-		if (existingInput) {
-			warning("Ignoring hardware input %s (id %s) because an input with the same id is already defined",
-			        entry->desc, entry->hwId);
-			continue;
+		if (!key || !key->hwId) {
+			return HardwareInput();
 		}
 
-		_customInput[entry->code] = new HardwareInput(entry->hwId, entry->code, entry->desc);
+		String id;
+		String fullKeyDesc;
+		byte modifierFlags = 0;
+
+		for (const ModifierTableEntry *modifier = _modifiers;  modifier->id; modifier++) {
+			if (event.kbd.hasFlags(modifier->flag)) {
+				id += modifier->id;
+				id += "+";
+				fullKeyDesc += modifier->desc;
+				modifierFlags |= modifier->flag;
+			}
+		}
+
+		const KeyState keystate = KeyState(key->keycode, 0, modifierFlags);
+		return HardwareInput(id + key->hwId, keystate, fullKeyDesc + key->desc);
+	}
+	default:
+		return HardwareInput();
 	}
 }
 
-void HardwareInputSet::addHardwareInputs(const KeyTableEntry keys[], const ModifierTableEntry modifiers[]) {
-	const KeyTableEntry *key;
-	const ModifierTableEntry *mod;
+CustomHardwareInputSet::CustomHardwareInputSet(const HardwareInputTableEntry *hardwareEntries) :
+		_hardwareEntries(hardwareEntries) {
+	assert(_hardwareEntries);
+}
 
-	for (mod = modifiers; mod->id; mod++) {
-		for (key = keys; key->hwId; key++) {
-			String keyId = String::format("%s%s", mod->id, key->hwId);
-			KeyState keystate = KeyState(key->keycode, 0, mod->flag);
+HardwareInput CustomHardwareInputSet::findHardwareInput(const String &id) const {
+	const HardwareInputTableEntry *hw = nullptr;
+	for (hw = _hardwareEntries;  hw->hwId; hw++) {
+		if (id.equals(hw->hwId)) {
+			break;
+		}
+	}
 
-			const HardwareInput *existingInput = findHardwareInput(keystate);
-			if (existingInput) {
-				warning("Ignoring hardware input %s%s (id %s) because an input with the same keystate is already defined",
-				        keys->desc, mod->desc, keyId.c_str());
-				continue;
-			}
+	if (!hw || !hw->hwId) {
+		return HardwareInput();
+	}
+
+	return HardwareInput(hw->hwId, hw->code, hw->desc);
+}
 
-			existingInput = findHardwareInput(keyId);
-			if (existingInput) {
-				warning("Ignoring hardware input %s%s (id %s) because an input with the same id is already defined",
-				        keys->desc, mod->desc, keyId.c_str());
-				continue;
+HardwareInput CustomHardwareInputSet::findHardwareInput(const Event &event) const {
+	switch (event.type) {
+	case EVENT_CUSTOM_BACKEND_HARDWARE: {
+		const HardwareInputTableEntry *hw = nullptr;
+		for (hw = _hardwareEntries;  hw->hwId; hw++) {
+			if (event.customType == hw->code) {
+				break;
 			}
+		}
+
+		if (!hw || !hw->hwId) {
+			return HardwareInput();
+		}
+
+		return HardwareInput(hw->hwId, hw->code, hw->desc);
+	}
+	default:
+		return HardwareInput();
+	}
+}
+
+CompositeHardwareInputSet::~CompositeHardwareInputSet() {
+	for (uint i = 0; i < _inputSets.size(); i++) {
+		delete _inputSets[i];
+	}
+}
 
-			String fullKeyDesc = String::format("%s%s", mod->desc, key->desc);
-			_keyInput[keystate] = new HardwareInput(keyId, keystate, fullKeyDesc);
+HardwareInput CompositeHardwareInputSet::findHardwareInput(const String &id) const {
+	for (uint i = 0; i < _inputSets.size(); i++) {
+		HardwareInput hardwareInput = _inputSets[i]->findHardwareInput(id);
+		if (hardwareInput.type != kHardwareInputTypeInvalid) {
+			return hardwareInput;
 		}
 	}
+
+	return HardwareInput();
+}
+
+HardwareInput CompositeHardwareInputSet::findHardwareInput(const Event &event) const {
+	for (uint i = 0; i < _inputSets.size(); i++) {
+		HardwareInput hardwareInput = _inputSets[i]->findHardwareInput(event);
+		if (hardwareInput.type != kHardwareInputTypeInvalid) {
+			return hardwareInput;
+		}
+	}
+
+	return HardwareInput();
 }
 
 } //namespace Common
diff --git a/backends/keymapper/hardware-input.h b/backends/keymapper/hardware-input.h
index 07d42bd..d2055dc 100644
--- a/backends/keymapper/hardware-input.h
+++ b/backends/keymapper/hardware-input.h
@@ -25,16 +25,18 @@
 
 #include "common/scummsys.h"
 
-#include "common/hashmap.h"
+#include "common/array.h"
+#include "common/events.h"
 #include "common/keyboard.h"
 #include "common/str.h"
-#include "common/textconsole.h"
 
 namespace Common {
 
 typedef uint32 HardwareInputCode;
 
 enum HardwareInputType {
+	/** Empty / invalid input type */
+	kHardwareInputTypeInvalid,
 	/** Input that sends single events */
 	kHardwareInputTypeGeneric,
 	/** Input that usually send -up and -down events */
@@ -51,7 +53,8 @@ struct HardwareInput {
 	/** Human readable description */
 	String description;
 
-	const HardwareInputType type;
+	/** Type tag */
+	HardwareInputType type;
 
 	/**
 	 * A platform specific unique identifier for an input event
@@ -67,13 +70,19 @@ struct HardwareInput {
 	 */
 	KeyState key;
 
-	HardwareInput(const String &i, HardwareInputCode ic = 0, const String &desc = "")
+	HardwareInput()
+		: inputCode(0), type(kHardwareInputTypeInvalid) { }
+
+	HardwareInput(const String &i, HardwareInputCode ic, const String &desc)
 		: id(i), inputCode(ic), description(desc), type(kHardwareInputTypeGeneric) { }
 
-	HardwareInput(const String &i, KeyState ky, const String &desc = "")
-		: id(i), key(ky), description(desc), type(kHardwareInputTypeKeyboard) { }
+	HardwareInput(const String &i, KeyState ky, const String &desc)
+		: id(i), inputCode(0), key(ky), description(desc), type(kHardwareInputTypeKeyboard) { }
 };
 
+/**
+ * Entry in a static table of custom backend hardware inputs
+ */
 struct HardwareInputTableEntry {
 	const char *hwId;
 	HardwareInputCode code;
@@ -99,61 +108,94 @@ struct ModifierTableEntry {
 };
 
 /**
- * Hash function for KeyState
+ * Interface for querying information about a hardware input device
  */
-template<> struct Hash<KeyState>
-		: public UnaryFunction<KeyState, uint> {
+class HardwareInputSet {
+public:
+	virtual ~HardwareInputSet();
+
+	/**
+	 * Retrieve a hardware input description from an unique identifier
+	 *
+	 * In case no input was found with the specified id, an empty
+	 * HardwareInput structure is return with the type set to
+	 * kHardwareInputTypeInvalid.
+	 */
+	virtual HardwareInput findHardwareInput(const String &id) const = 0;
 
-	uint operator()(const KeyState &val) const {
-		return (uint)val.keycode | ((uint)val.flags << 24);
-	}
+	/**
+	 * Retrieve a hardware input description from one of the events
+	 * produced when the input is triggered.
+	 *
+	 * In case the specified event is not produced by this device,
+	 * an empty HardwareInput structure is return with the type set to
+	 * kHardwareInputTypeInvalid.
+	 */
+	virtual HardwareInput findHardwareInput(const Event &event) const = 0;
 };
 
 /**
- * Simple class to encapsulate a device's set of HardwareInputs.
- * Each device should instantiate this and call addHardwareInput a number of times
- * in its constructor to define the device's available keys.
+ * A keyboard input device
+ *
+ * Describes the keys and key + modifiers combinations as HardwareInputs
  */
-class HardwareInputSet {
+class KeyboardHardwareInputSet : public HardwareInputSet {
 public:
+	KeyboardHardwareInputSet(const KeyTableEntry *keys, const ModifierTableEntry *modifiers);
 
-	/**
-	 * Add hardware input keys to the set out of key and modifier tables.
-	 * @param useDefault	auto-add the built-in default inputs
-	 * @param keys       	table of available keys
-	 * @param modifiers  	table of available modifiers
-	 */
-	HardwareInputSet(bool useDefault = false, const KeyTableEntry keys[] = 0, const ModifierTableEntry modifiers[] = 0);
+	// HardwareInputSet API
+	HardwareInput findHardwareInput(const String &id) const override;
+	HardwareInput findHardwareInput(const Event &event) const override;
 
-	virtual ~HardwareInputSet();
+private:
+	const KeyTableEntry *_keys;
+	const ModifierTableEntry *_modifiers;
+};
+
+/**
+ * A custom backend input device
+ *
+ * @todo This is currently unused. Perhaps it should be removed.
+ */
+class CustomHardwareInputSet : public HardwareInputSet {
+public:
+	CustomHardwareInputSet(const HardwareInputTableEntry *hardwareEntries);
 
-	const HardwareInput *findHardwareInput(const String &id) const;
+	// HardwareInputSet API
+	HardwareInput findHardwareInput(const String &id) const override;
+	HardwareInput findHardwareInput(const Event &event) const override;
 
-	const HardwareInput *findHardwareInput(const HardwareInputCode code) const;
+private:
+	const HardwareInputTableEntry *_hardwareEntries;
+};
 
-	const HardwareInput *findHardwareInput(const KeyState &keystate) const;
+/**
+ * A composite input device that delegates to a set of actual input devices.
+ */
+class CompositeHardwareInputSet : public HardwareInputSet {
+public:
+	~CompositeHardwareInputSet() override;
 
-	/**
-	 * Add hardware inputs to the set out of a table.
-	 * @param inputs       table of available inputs
-	 */
-	void addHardwareInputs(const HardwareInputTableEntry inputs[]);
+	// HardwareInputSet API
+	HardwareInput findHardwareInput(const String &id) const override;
+	HardwareInput findHardwareInput(const Event &event) const override;
 
 	/**
-	 * 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 an input device to this composite device
+	 *
+	 * Takes ownership of the hardware input set
 	 */
-	void addHardwareInputs(const KeyTableEntry keys[], const ModifierTableEntry modifiers[]);
+	void addHardwareInputSet(HardwareInputSet *hardwareInputSet);
 
 private:
+	Array<HardwareInputSet *> _inputSets;
+};
 
-	typedef HashMap<KeyState, const HardwareInput *> KeyInputMap;
-	typedef HashMap<HardwareInputCode, const HardwareInput *> CustomInputMap;
+/** A standard set of keyboard keys */
+extern const KeyTableEntry defaultKeys[];
 
-	KeyInputMap _keyInput;
-	CustomInputMap _customInput;
-};
+/** A standard set of keyboard modifiers */
+extern const ModifierTableEntry defaultModifiers[];
 
 } // End of namespace Common
 
diff --git a/backends/keymapper/input-watcher.cpp b/backends/keymapper/input-watcher.cpp
index 0dc989b..90b0218 100644
--- a/backends/keymapper/input-watcher.cpp
+++ b/backends/keymapper/input-watcher.cpp
@@ -30,14 +30,13 @@ namespace Common {
 InputWatcher::InputWatcher(EventDispatcher *eventDispatcher, Keymapper *keymapper) :
 		_eventDispatcher(eventDispatcher),
 		_keymapper(keymapper),
-		_watching(false),
-		_hwInput(nullptr) {
+		_watching(false) {
 
 }
 
 void InputWatcher::startWatching() {
 	assert(!_watching);
-	assert(!_hwInput);
+	assert(_hwInput.type == kHardwareInputTypeInvalid);
 
 	_keymapper->setEnabled(false);
 	_eventDispatcher->registerObserver(this, EventManager::kEventRemapperPriority, false);
@@ -56,7 +55,7 @@ bool InputWatcher::isWatching() const {
 
 bool InputWatcher::notifyEvent(const Event &event) {
 	assert(_watching);
-	assert(!_hwInput);
+	assert(_hwInput.type == kHardwareInputTypeInvalid);
 
 	switch (event.type) {
 		case EVENT_KEYDOWN:
@@ -64,7 +63,7 @@ bool InputWatcher::notifyEvent(const Event &event) {
 		case EVENT_KEYUP:
 		case EVENT_CUSTOM_BACKEND_HARDWARE:
 			_hwInput = _keymapper->findHardwareInput(event);
-			if (_hwInput) {
+			if (_hwInput.type != kHardwareInputTypeInvalid) {
 				stopWatching();
 			}
 			return true;
@@ -75,9 +74,9 @@ bool InputWatcher::notifyEvent(const Event &event) {
 	return false;
 }
 
-const HardwareInput *InputWatcher::checkForCapturedInput() {
-	const HardwareInput *hwInput = _hwInput;
-	_hwInput = nullptr;
+HardwareInput InputWatcher::checkForCapturedInput() {
+	HardwareInput hwInput = _hwInput;
+	_hwInput = HardwareInput();
 	return hwInput;
 }
 
diff --git a/backends/keymapper/input-watcher.h b/backends/keymapper/input-watcher.h
index 5818fe6..672edb6 100644
--- a/backends/keymapper/input-watcher.h
+++ b/backends/keymapper/input-watcher.h
@@ -25,6 +25,7 @@
 
 #include "common/scummsys.h"
 
+#include "backends/keymapper/hardware-input.h"
 #include "common/events.h"
 
 namespace Common {
@@ -48,7 +49,7 @@ public:
 	void stopWatching();
 
 	bool isWatching() const;
-	const HardwareInput *checkForCapturedInput();
+	HardwareInput checkForCapturedInput();
 
 private:
 	bool notifyEvent(const Event &event) override;
@@ -57,7 +58,7 @@ private:
 	Keymapper *_keymapper;
 
 	bool _watching;
-	const HardwareInput *_hwInput;
+	HardwareInput _hwInput;
 };
 
 } // End of namespace Common
diff --git a/backends/keymapper/keymap.cpp b/backends/keymapper/keymap.cpp
index 917d3ec..5a306db 100644
--- a/backends/keymapper/keymap.cpp
+++ b/backends/keymapper/keymap.cpp
@@ -55,7 +55,7 @@ void Keymap::addAction(Action *action) {
 	_actions.push_back(action);
 }
 
-void Keymap::registerMapping(Action *action, const HardwareInput *hwInput) {
+void Keymap::registerMapping(Action *action, const HardwareInput &hwInput) {
 	ActionArray &actionArray = _hwActionMap.getVal(hwInput);
 
 	// Don't allow an input to map to the same action multiple times
@@ -87,8 +87,8 @@ void Keymap::resetMapping(Action *action) {
 	registerMappings(action, hwInputIds);
 }
 
-Array<const HardwareInput *> Keymap::getActionMapping(Action *action) const {
-	Array<const HardwareInput *> inputs;
+Array<HardwareInput> Keymap::getActionMapping(Action *action) const {
+	Array<HardwareInput> inputs;
 
 	for (HardwareActionMap::iterator itInput = _hwActionMap.begin(); itInput != _hwActionMap.end(); itInput++) {
 		for (ActionArray::iterator itAction = itInput->_value.begin(); itAction != itInput->_value.end(); itAction++) {
@@ -111,8 +111,20 @@ const Action *Keymap::findAction(const char *id) const {
 	return nullptr;
 }
 
-const Keymap::ActionArray &Keymap::getMappedActions(const HardwareInput *hardwareInput) const {
-	return _hwActionMap[hardwareInput];
+Keymap::ActionArray Keymap::getMappedActions(const Event &event) const {
+	switch (event.type) {
+	case EVENT_KEYDOWN:
+	case EVENT_KEYUP: {
+		HardwareInput hardwareInput("", event.kbd, "");
+		return _hwActionMap[hardwareInput];
+	}
+	case EVENT_CUSTOM_BACKEND_HARDWARE: {
+		HardwareInput hardwareInput("", event.customType, "");
+		return _hwActionMap[hardwareInput];
+	}
+	default:
+		return ActionArray();
+	}
 }
 
 void Keymap::setConfigDomain(ConfigManager::Domain *configDomain) {
@@ -188,9 +200,9 @@ void Keymap::registerMappings(Action *action, const Array <String> &hwInputIds)
 	assert(_hardwareInputSet);
 
 	for (uint i = 0; i < hwInputIds.size(); i++) {
-			const HardwareInput *hwInput = _hardwareInputSet->findHardwareInput(hwInputIds[i].c_str());
+			HardwareInput hwInput = _hardwareInputSet->findHardwareInput(hwInputIds[i].c_str());
 
-			if (!hwInput) {
+			if (hwInput.type == kHardwareInputTypeInvalid) {
 				// Silently ignore unknown hardware ids because the current device may not have inputs matching the defaults
 				debug(1, "HardwareInput with ID '%s' not known", hwInputIds[i].c_str());
 				continue;
@@ -209,7 +221,7 @@ void Keymap::saveMappings() {
 
 	for (ActionArray::const_iterator it = _actions.begin(); it != _actions.end(); it++) {
 		Action *action = *it;
-		Array<const HardwareInput *> mappedInputs = getActionMapping(action);
+		Array<HardwareInput> mappedInputs = getActionMapping(action);
 
 		if (areMappingsIdentical(mappedInputs, action->getDefaultInputMapping())) {
 			// If the current mapping is the default, don't write anything to the config manager
@@ -224,14 +236,14 @@ void Keymap::saveMappings() {
 				confValue += " ";
 			}
 
-			confValue += mappedInputs[j]->id;
+			confValue += mappedInputs[j].id;
 		}
 
 		_configDomain->setVal(prefix + action->id, confValue);
 	}
 }
 
-bool Keymap::areMappingsIdentical(const Array<const HardwareInput *> &inputs, const Array<String> &mapping) {
+bool Keymap::areMappingsIdentical(const Array<HardwareInput> &inputs, const StringArray &mapping) {
 	if (inputs.size() != mapping.size()) {
 		return false;
 	}
@@ -241,7 +253,7 @@ bool Keymap::areMappingsIdentical(const Array<const HardwareInput *> &inputs, co
 	uint foundCount = 0;
 	for (uint i = 0; i < inputs.size(); i++) {
 		for (uint j = 0; j < mapping.size(); j++) {
-			if (inputs[i]->id == mapping[j]) {
+			if (inputs[i].id == mapping[j]) {
 				foundCount++;
 				break;
 			}
diff --git a/backends/keymapper/keymap.h b/backends/keymapper/keymap.h
index 1cdc538..7abc439 100644
--- a/backends/keymapper/keymap.h
+++ b/backends/keymapper/keymap.h
@@ -25,21 +25,44 @@
 
 #include "common/scummsys.h"
 
+#include "backends/keymapper/hardware-input.h"
+
 #include "common/config-manager.h"
 #include "common/func.h"
 #include "common/hashmap.h"
 #include "common/hash-ptr.h"
 #include "common/list.h"
+#include "common/str-array.h"
 
 namespace Common {
 
 const char *const kStandardActionsKeymapName = "standard-actions";
 
 class Action;
+class Event;
 struct HardwareInput;
 class HardwareInputSet;
 class KeymapperDefaultBindings;
 
+struct Event_EqualTo {
+	bool operator()(const HardwareInput& x, const HardwareInput& y) const {
+		return (x.type == y.type)
+		        && (x.key == y.key) // TODO: Remove the equality operator from KeyState
+		        && (x.inputCode == y.inputCode);
+	}
+};
+
+struct Event_Hash {
+	uint operator()(const HardwareInput& x) const {
+		uint hash = 7;
+		hash = 31 * hash + x.type;
+		hash = 31 * hash + x.key.keycode;
+		hash = 31 * hash + (x.key.flags & ~KBD_STICKY);
+		hash = 31 * hash + x.inputCode;
+		return hash;
+	}
+};
+
 class Keymap {
 public:
 	enum KeymapType {
@@ -62,7 +85,7 @@ public:
 	* @param key pointer to HardwareInput to map
 	* @see Action::mapKey
 	*/
-	void registerMapping(Action *action, const HardwareInput *input);
+	void registerMapping(Action *action, const HardwareInput &input);
 
 	/**
 	* Unregisters a HardwareInput from the given Action (if one is mapped)
@@ -80,14 +103,14 @@ public:
 	/**
 	 * Find the hardware input an action is mapped to, if any
 	 */
-	Array<const HardwareInput *> getActionMapping(Action *action) const;
+	Array<HardwareInput> getActionMapping(Action *action) const;
 
 	/**
 	 * Find the Actions that a hardware input is mapped to
 	 * @param hardwareInput	the input that is mapped to the required Action
 	 * @return		an array containing pointers to the actions
 	 */
-	const ActionArray &getMappedActions(const HardwareInput *hardwareInput) const;
+	ActionArray getMappedActions(const Event &event) const;
 
 	/**
 	 * Adds a new Action to this Map
@@ -129,10 +152,10 @@ private:
 
 	const Action *findAction(const char *id) const;
 
-	void registerMappings(Action *action, const Array<String> &hwInputIds);
-	bool areMappingsIdentical(const Array<const HardwareInput *> &inputs, const Array <String> &mapping);
+	void registerMappings(Action *action, const StringArray &hwInputIds);
+	bool areMappingsIdentical(const Array<HardwareInput> &inputs, const StringArray &mapping);
 
-	typedef HashMap<const HardwareInput *, ActionArray> HardwareActionMap;
+	typedef HashMap<HardwareInput, ActionArray, Event_Hash, Event_EqualTo> HardwareActionMap;
 
 	KeymapType _type;
 	String _name;
diff --git a/backends/keymapper/keymapper.cpp b/backends/keymapper/keymapper.cpp
index ce39980..46202c6 100644
--- a/backends/keymapper/keymapper.cpp
+++ b/backends/keymapper/keymapper.cpp
@@ -56,7 +56,7 @@ void Keymapper::registerHardwareInputSet(HardwareInputSet *inputs) {
 
 	if (!inputs) {
 		warning("No hardware input were defined, using defaults");
-		inputs = new HardwareInputSet(true);
+		inputs = new KeyboardHardwareInputSet(defaultKeys, defaultModifiers);
 	}
 
 	_hardwareInputs = inputs;
@@ -147,13 +147,6 @@ List<Event> Keymapper::mapEvent(const Event &ev) {
 
 	hardcodedEventMapping(ev);
 
-	const HardwareInput *hwInput = findHardwareInput(ev);
-	if (!hwInput) {
-		List<Event> originalEvent;
-		originalEvent.push_back(ev);
-		return originalEvent;
-	}
-
 	IncomingEventType incomingEventType = convertToIncomingEventType(ev);
 
 	List<Event> mappedEvents;
@@ -169,7 +162,7 @@ List<Event> Keymapper::mapEvent(const Event &ev) {
 
 		debug(5, "Keymapper::mapKey keymap: %s", _keymaps[i]->getName().c_str());
 
-		const Keymap::ActionArray &actions = _keymaps[i]->getMappedActions(hwInput);
+		const Keymap::ActionArray &actions = _keymaps[i]->getMappedActions(ev);
 		for (Keymap::ActionArray::const_iterator it = actions.begin(); it != actions.end(); it++) {
 			mappedEvents.push_back(executeAction(*it, incomingEventType));
 		}
@@ -261,16 +254,8 @@ EventType Keymapper::convertStartToEnd(EventType type) {
 	return result;
 }
 
-const HardwareInput *Keymapper::findHardwareInput(const Event &event) {
-	switch (event.type) {
-		case EVENT_KEYDOWN:
-		case EVENT_KEYUP:
-			return _hardwareInputs->findHardwareInput(event.kbd);
-		case EVENT_CUSTOM_BACKEND_HARDWARE:
-			return _hardwareInputs->findHardwareInput(event.customType);
-		default:
-			return nullptr;
-	}
+HardwareInput Keymapper::findHardwareInput(const Event &event) {
+	return _hardwareInputs->findHardwareInput(event);
 }
 
 void Keymapper::hardcodedEventMapping(Event ev) {
diff --git a/backends/keymapper/keymapper.h b/backends/keymapper/keymapper.h
index c5ee304..9e3e3f7 100644
--- a/backends/keymapper/keymapper.h
+++ b/backends/keymapper/keymapper.h
@@ -121,7 +121,7 @@ public:
 	/**
 	 * Return a HardwareInput pointer for the given event
 	 */
-	const HardwareInput *findHardwareInput(const Event &event);
+	HardwareInput findHardwareInput(const Event &event);
 
 	void initKeymap(Keymap *keymap, ConfigManager::Domain *domain);
 
diff --git a/backends/keymapper/remap-widget.cpp b/backends/keymapper/remap-widget.cpp
index d96b737..7a87519 100644
--- a/backends/keymapper/remap-widget.cpp
+++ b/backends/keymapper/remap-widget.cpp
@@ -216,8 +216,8 @@ void RemapWidget::handleMouseDown(int x, int y, int button, int clickCount) {
 }
 
 void RemapWidget::handleTickle() {
-	const HardwareInput *hardwareInput = _remapInputWatcher->checkForCapturedInput();
-	if (hardwareInput) {
+	const HardwareInput hardwareInput = _remapInputWatcher->checkForCapturedInput();
+	if (hardwareInput.type != kHardwareInputTypeInvalid) {
 		_remapKeymap->registerMapping(_remapAction, hardwareInput);
 
 		_changes = true;
@@ -260,7 +260,7 @@ void RemapWidget::refreshKeymap() {
 
 		row.actionText->setLabel(row.action->description);
 
-		Array<const HardwareInput *> mappedInputs = row.keymap->getActionMapping(row.action);
+		Array<HardwareInput> mappedInputs = row.keymap->getActionMapping(row.action);
 
 		String keysLabel;
 		for (uint j = 0; j < mappedInputs.size(); j++) {
@@ -268,7 +268,7 @@ void RemapWidget::refreshKeymap() {
 				keysLabel += ", ";
 			}
 
-			keysLabel += mappedInputs[j]->description;
+			keysLabel += mappedInputs[j].description;
 		}
 
 		if (!keysLabel.empty()) {
diff --git a/backends/platform/linuxmoto/hardwarekeys.cpp b/backends/platform/linuxmoto/hardwarekeys.cpp
index 5d18aee..449dd3f 100644
--- a/backends/platform/linuxmoto/hardwarekeys.cpp
+++ b/backends/platform/linuxmoto/hardwarekeys.cpp
@@ -103,7 +103,3 @@ static const Mod modifiers[] = {
 	{ KBD_SHIFT | KBD_CTRL | KBD_ALT, "C+A+", "Ctrl+Alt+", true },
 	{ 0, 0, 0, false }
 };
-
-Common::HardwareInputSet *OSystem_LINUXMOTO::getHardwareInputSet() {
-	return OSystem_SDL::getHardwareInputSet();
-}
diff --git a/backends/platform/maemo/maemo.cpp b/backends/platform/maemo/maemo.cpp
index b2e4990..517b3ce 100644
--- a/backends/platform/maemo/maemo.cpp
+++ b/backends/platform/maemo/maemo.cpp
@@ -184,7 +184,11 @@ static const Common::KeyTableEntry maemoKeys[] = {
 };
 
 Common::HardwareInputSet *OSystem_SDL_Maemo::getHardwareInputSet() {
-	return new Common::HardwareInputSet(true, maemoKeys);
+	Common::CompositeHardwareInputSet inputSet = new Common::CompositeHardwareInputSet();
+	inputSet->addHardwareInputSet(new Common::KeyboardHardwareInputSet(maemoKeys, defaultModifiers));
+	inputSet->addHardwareInputSet(new Common::KeyboardHardwareInputSet(defaultKeys, defaultModifiers));
+
+	return inputSet;
 }
 
 Common::KeymapArray OSystem_SDL_Maemo::getGlobalKeymaps() {


Commit: 85f476070b00478545683379e3ef5ac7707206c9
    https://github.com/scummvm/scummvm/commit/85f476070b00478545683379e3ef5ac7707206c9
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
PEGASUS: Use custom engine actions for key input

Changed paths:
    engines/pegasus/input.cpp
    engines/pegasus/input.h
    engines/pegasus/pegasus.cpp


diff --git a/engines/pegasus/input.cpp b/engines/pegasus/input.cpp
index b44deff..42edf35 100644
--- a/engines/pegasus/input.cpp
+++ b/engines/pegasus/input.cpp
@@ -40,33 +40,9 @@ namespace Pegasus {
 
 InputDeviceManager::InputDeviceManager() {
 	// Set all keys to "not down"
-	_keyMap[Common::KEYCODE_UP] = false;
-	_keyMap[Common::KEYCODE_KP8] = false;
-	_keyMap[Common::KEYCODE_LEFT] = false;
-	_keyMap[Common::KEYCODE_KP4] = false;
-	_keyMap[Common::KEYCODE_DOWN] = false;
-	_keyMap[Common::KEYCODE_KP5] = false;
-	_keyMap[Common::KEYCODE_RIGHT] = false;
-	_keyMap[Common::KEYCODE_KP6] = false;
-	_keyMap[Common::KEYCODE_RETURN] = false;
-	_keyMap[Common::KEYCODE_SPACE] = false;
-	_keyMap[Common::KEYCODE_t] = false;
-	_keyMap[Common::KEYCODE_KP_EQUALS] = false;
-	_keyMap[Common::KEYCODE_i] = false;
-	_keyMap[Common::KEYCODE_KP_DIVIDE] = false;
-	_keyMap[Common::KEYCODE_q] = false;
-	_keyMap[Common::KEYCODE_ESCAPE] = false;
-	_keyMap[Common::KEYCODE_p] = false;
-	_keyMap[Common::KEYCODE_TILDE] = false;
-	_keyMap[Common::KEYCODE_BACKQUOTE] = false;
-	_keyMap[Common::KEYCODE_KP7] = false;
-	_keyMap[Common::KEYCODE_BACKSPACE] = false;
-	_keyMap[Common::KEYCODE_KP_MULTIPLY] = false;
-	_keyMap[Common::KEYCODE_KP9] = false;
-	_keyMap[Common::KEYCODE_LALT] = false;
-	_keyMap[Common::KEYCODE_RALT] = false;
-	_keyMap[Common::KEYCODE_e] = false;
-	_keyMap[Common::KEYCODE_KP_ENTER] = false;
+	for (uint i = 0; i < ARRAYSIZE(_keysDown); i++) {
+		_keysDown[i] = false;
+	}
 
 	g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 2, false);
 	_lastRawBits = kAllUpBits;
@@ -89,46 +65,34 @@ void InputDeviceManager::getInput(Input &input, const InputBits filter) {
 	// Now create the bitfield
 	InputBits currentBits = 0;
 
-	if (_keyMap[Common::KEYCODE_UP] || _keyMap[Common::KEYCODE_KP8])
+	if (_keysDown[kPegasusActionUp])
 		currentBits |= (kRawButtonDown << kUpButtonShift);
 
-	if (_keyMap[Common::KEYCODE_DOWN] || _keyMap[Common::KEYCODE_KP5])
+	if (_keysDown[kPegasusActionDown])
 		currentBits |= (kRawButtonDown << kDownButtonShift);
 
-	if (_keyMap[Common::KEYCODE_LEFT] || _keyMap[Common::KEYCODE_KP4])
+	if (_keysDown[kPegasusActionLeft])
 		currentBits |= (kRawButtonDown << kLeftButtonShift);
 
-	if (_keyMap[Common::KEYCODE_RIGHT] || _keyMap[Common::KEYCODE_KP6])
+	if (_keysDown[kPegasusActionRight])
 		currentBits |= (kRawButtonDown << kRightButtonShift);
 
-	if (_keyMap[Common::KEYCODE_SPACE] || _keyMap[Common::KEYCODE_RETURN] || _keyMap[Common::KEYCODE_KP_ENTER])
+	if (_keysDown[kPegasusActionInteract])
 		currentBits |= (kRawButtonDown << kTwoButtonShift);
 
-	if (_keyMap[Common::KEYCODE_t] || _keyMap[Common::KEYCODE_KP_EQUALS])
+	if (_keysDown[kPegasusActionToggleCenterDisplay])
 		currentBits |= (kRawButtonDown << kThreeButtonShift);
 
-	if (_keyMap[Common::KEYCODE_i] || _keyMap[Common::KEYCODE_KP_DIVIDE])
+	if (_keysDown[kPegasusActionShowInfoScreen])
 		currentBits |= (kRawButtonDown << kFourButtonShift);
 
-	if (_keyMap[Common::KEYCODE_q])
-		currentBits |= (kRawButtonDown << kMod1ButtonShift);
-
-	if (_keyMap[Common::KEYCODE_ESCAPE] || _keyMap[Common::KEYCODE_p])
+	if (_keysDown[kPegasusActionShowPauseMenu])
 		currentBits |= (kRawButtonDown << kMod3ButtonShift);
 
-	// The original also used clear (aka "num lock" on Mac keyboards) here, but it doesn't
-	// work right on most systems. Either SDL or the OS treats num lock specially and the
-	// events don't come as expected. In many cases, the key down event is sent many times
-	// causing the drawer to open and close constantly until pressed again. It only causes
-	// more grief than anything else.
-
-	// The original doesn't use KP7 for inventory, but we're using it as an alternative for
-	// num lock. KP9 is used for the biochip drawer to balance things out.
-
-	if (_keyMap[Common::KEYCODE_TILDE] || _keyMap[Common::KEYCODE_BACKQUOTE] || _keyMap[Common::KEYCODE_KP7])
+	if (_keysDown[kPegasusActionShowInventory])
 		currentBits |= (kRawButtonDown << kLeftFireButtonShift);
 
-	if (_keyMap[Common::KEYCODE_BACKSPACE] || _keyMap[Common::KEYCODE_KP_MULTIPLY] || _keyMap[Common::KEYCODE_KP9])
+	if (_keysDown[kPegasusActionShowBiochip])
 		currentBits |= (kRawButtonDown << kRightFireButtonShift);
 
 	// Update mouse button state
@@ -157,10 +121,7 @@ void InputDeviceManager::getInput(Input &input, const InputBits filter) {
 	// trying to do alt+enter or something). Since it's only used
 	// as an easter egg, I'm just going to handle it as a separate
 	// bool value.
-	// WORKAROUND x2: I'm also accepting 'e' here since an
-	// alt+click is often intercepted by the OS. 'e' is used as the
-	// easter egg key in Buried in Time and Legacy of Time.
-	input.setAltDown(_keyMap[Common::KEYCODE_LALT] || _keyMap[Common::KEYCODE_RALT] || _keyMap[Common::KEYCODE_e]);
+	input.setAltDown(_keysDown[kPegasusActionEnableEasterEgg]);
 }
 
 // Wait until the input device stops returning input allowed by filter...
@@ -175,35 +136,35 @@ void InputDeviceManager::waitInput(const InputBits filter) {
 	}
 }
 
-uint InputDeviceManager::convertJoystickToKey(uint joybutton) {
+PegasusAction InputDeviceManager::convertJoystickToKey(uint joybutton) {
 	switch (joybutton) {
 	case Common::JOYSTICK_BUTTON_A:
-		return Common::KEYCODE_RETURN; // Action
+		return kPegasusActionInteract;
 	case Common::JOYSTICK_BUTTON_B:
 		// nothing
 		break;
 	case Common::JOYSTICK_BUTTON_X:
-		return Common::KEYCODE_i; // Display Object Info
+		return kPegasusActionShowInfoScreen;
 	case Common::JOYSTICK_BUTTON_Y:
-		return Common::KEYCODE_t; // Toggle Data Display
+		return kPegasusActionToggleCenterDisplay;
 	case Common::JOYSTICK_BUTTON_LEFT_SHOULDER:
-		return Common::KEYCODE_TILDE; // Open Inventory Panel
+		return kPegasusActionShowInventory;
 	case Common::JOYSTICK_BUTTON_RIGHT_SHOULDER:
-		return Common::KEYCODE_KP_MULTIPLY; // Open Biochip Panel
+		return kPegasusActionShowBiochip;
 	case Common::JOYSTICK_BUTTON_BACK:
-		return Common::KEYCODE_p; // Pause
+		return kPegasusActionShowPauseMenu;
 	case Common::JOYSTICK_BUTTON_DPAD_UP:
-		return Common::KEYCODE_UP;
+		return kPegasusActionUp;
 	case Common::JOYSTICK_BUTTON_DPAD_DOWN:
-		return Common::KEYCODE_DOWN;
+		return kPegasusActionDown;
 	case Common::JOYSTICK_BUTTON_DPAD_LEFT:
-		return Common::KEYCODE_LEFT;
+		return kPegasusActionLeft;
 	case Common::JOYSTICK_BUTTON_DPAD_RIGHT:
-		return Common::KEYCODE_RIGHT;
+		return kPegasusActionRight;
 	default:
 		break;
 	}
-	return 0;
+	return kPegasusActionNone;
 }
 
 bool InputDeviceManager::notifyEvent(const Common::Event &event) {
@@ -217,44 +178,38 @@ bool InputDeviceManager::notifyEvent(const Common::Event &event) {
 	// are based on pippin events.
 
 	switch (event.type) {
-	case Common::EVENT_KEYDOWN:
-		switch (event.kbd.keycode) {
-		case Common::KEYCODE_d:
-			if (event.kbd.flags & Common::KBD_CTRL) // Console!
-				_consoleRequested = true;
+	case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
+		switch ((PegasusAction)event.customType) {
+		case kPegasusActionOpenDebugger:
+			_consoleRequested = true;
 			break;
-		case Common::KEYCODE_s:
-			// We support meta where available and control elsewhere
-			if (event.kbd.flags & (Common::KBD_CTRL|Common::KBD_META))
-				((PegasusEngine *)g_engine)->requestSave();
+		case kPegasusActionSaveGameState:
+			((PegasusEngine *)g_engine)->requestSave();
 			break;
-		case Common::KEYCODE_o: // o for open (original)
-		case Common::KEYCODE_l: // l for load (ScummVM terminology)
-			// We support meta where available and control elsewhere
-			if (event.kbd.flags & (Common::KBD_CTRL|Common::KBD_META))
-				((PegasusEngine *)g_engine)->requestLoad();
+		case kPegasusActionLoadGameState:
+			((PegasusEngine *)g_engine)->requestLoad();
 			break;
 		default:
-			// Otherwise, set the key to down if we have it
-			if (_keyMap.contains(event.kbd.keycode))
-				_keyMap[event.kbd.keycode] = true;
+			// Otherwise, set the action to down if we have it
+			if (event.customType != kPegasusActionNone && event.customType < kPegasusActionCount)
+				_keysDown[event.customType] = true;
 			break;
 		}
 		break;
-	case Common::EVENT_KEYUP:
+	case Common::EVENT_CUSTOM_ENGINE_ACTION_END:
 		// Set the key to up if we have it
-		if (_keyMap.contains(event.kbd.keycode))
-			_keyMap[event.kbd.keycode] = false;
+		if (event.customType != kPegasusActionNone && event.customType < kPegasusActionCount)
+			_keysDown[event.customType] = false;
 		break;
 	case Common::EVENT_JOYAXIS_MOTION:
 		break;
 	case Common::EVENT_JOYBUTTON_DOWN:
-		if (_keyMap.contains(convertJoystickToKey(event.joystick.button)))
-			_keyMap[convertJoystickToKey(event.joystick.button)] = true;
+		if (convertJoystickToKey(event.joystick.button) != kPegasusActionNone)
+			_keysDown[convertJoystickToKey(event.joystick.button)] = true;
 		break;
 	case Common::EVENT_JOYBUTTON_UP:
-		if (_keyMap.contains(convertJoystickToKey(event.joystick.button)))
-			_keyMap[convertJoystickToKey(event.joystick.button)] = false;
+		if (convertJoystickToKey(event.joystick.button) != kPegasusActionNone)
+			_keysDown[convertJoystickToKey(event.joystick.button)] = false;
 		break;
 	default:
 		break;
diff --git a/engines/pegasus/input.h b/engines/pegasus/input.h
index 3b06b15..f9ec00a 100644
--- a/engines/pegasus/input.h
+++ b/engines/pegasus/input.h
@@ -27,7 +27,6 @@
 #define PEGASUS_INPUT_H
 
 #include "common/events.h"
-#include "common/hashmap.h"
 #include "common/rect.h"
 #include "common/singleton.h"
 
@@ -39,6 +38,26 @@ namespace Pegasus {
 class Hotspot;
 class Input;
 
+enum PegasusAction {
+	kPegasusActionNone,
+	kPegasusActionUp,
+	kPegasusActionDown,
+	kPegasusActionLeft,
+	kPegasusActionRight,
+	kPegasusActionInteract,
+	kPegasusActionShowInventory,
+	kPegasusActionShowBiochip,
+	kPegasusActionToggleCenterDisplay,
+	kPegasusActionShowInfoScreen,
+	kPegasusActionShowPauseMenu,
+	kPegasusActionSaveGameState,
+	kPegasusActionLoadGameState,
+	kPegasusActionOpenDebugger,
+	kPegasusActionEnableEasterEgg,
+
+	kPegasusActionCount
+};
+
 class InputDeviceManager : public Common::Singleton<InputDeviceManager>, public Common::EventObserver {
 public:
 	InputDeviceManager();
@@ -52,13 +71,13 @@ public:
 
 	void pumpEvents();
 
-	uint convertJoystickToKey(uint joybutton);
+	PegasusAction convertJoystickToKey(uint joybutton);
 
 protected:
 	friend class Common::Singleton<SingletonBaseType>;
 
 	// Keep track of which keys are down (= true) or not
-	Common::HashMap<uint, bool> _keyMap;
+	bool _keysDown[kPegasusActionCount];
 	InputBits _lastRawBits;
 	bool _consoleRequested;
 };
diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp
index 826c892..98f29d2 100644
--- a/engines/pegasus/pegasus.cpp
+++ b/engines/pegasus/pegasus.cpp
@@ -35,6 +35,7 @@
 #include "common/random.h"
 #include "backends/keymapper/action.h"
 #include "backends/keymapper/keymapper.h"
+#include "backends/keymapper/standard-actions.h"
 #include "base/plugins.h"
 #include "base/version.h"
 #include "gui/message.h"
@@ -157,7 +158,6 @@ Common::Error PegasusEngine::run() {
 	}
 
 	// Set up input
-	initKeymap();
 	InputHandler::setInputHandler(this);
 	allowInput(true);
 
@@ -2490,30 +2490,111 @@ uint PegasusEngine::getNeighborhoodCD(const NeighborhoodID neighborhood) const {
 }
 
 Common::Keymap *PegasusEngine::initKeymap() {
-	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, "pegasus");
-
-	// Since the game has multiple built-in keys for each of these anyway,
-	// this just attempts to remap one of them.
-	const Common::KeyActionEntry keyActionEntries[] = {
-		{ "UP",  Common::KEYCODE_UP,        "UP",        _("Up/Zoom In/Move Forward/Open Doors") },
-		{ "DWN", Common::KEYCODE_DOWN,      "DOWN",      _("Down/Zoom Out")                      },
-		{ "TL",  Common::KEYCODE_LEFT,      "LEFT",      _("Turn Left")                          },
-		{ "TR",  Common::KEYCODE_RIGHT,     "RIGHT",     _("Turn Right")                         },
-		{ "TIV", Common::KEYCODE_BACKQUOTE, "BACKQUOTE", _("Display/Hide Inventory Tray")        },
-		{ "TBI", Common::KEYCODE_BACKSPACE, "BACKSPACE", _("Display/Hide Biochip Tray")          },
-		{ "ENT", Common::KEYCODE_RETURN,    "RETURN",    _("Action/Select")                      },
-		{ "TMA", Common::KEYCODE_t,         "t",         _("Toggle Center Data Display")         },
-		{ "TIN", Common::KEYCODE_i,         "i",         _("Display/Hide Info Screen")           },
-		{ "PM",  Common::KEYCODE_ESCAPE,    "ESCAPE",    _("Display/Hide Pause Menu")            },
-		{ "WTF", Common::KEYCODE_e,         "e",         "???" } // easter egg key (without being completely upfront about it)
-	};
-
-	for (uint i = 0; i < ARRAYSIZE(keyActionEntries); i++) {
-		Common::Action *const act = new Common::Action(keyActionEntries[i].id, keyActionEntries[i].description);
-		act->setKeyEvent(keyActionEntries[i].ks);
-		act->addDefaultInputMapping(keyActionEntries[i].defaultHwId);
-		engineKeyMap->addAction(act);
-	}
+	using namespace Common;
+
+	Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "pegasus");
+
+	Action *act;
+
+	act = new Action(kStandardActionMoveForward, _("Up/Zoom In/Move Forward/Open Doors"));
+	act->setCustomEngineActionEvent(kPegasusActionUp);
+	act->addDefaultInputMapping("UP");
+	act->addDefaultInputMapping("KP8");
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionMoveBackwards, _("Down/Zoom Out"));
+	act->setCustomEngineActionEvent(kPegasusActionDown);
+	act->addDefaultInputMapping("DOWN");
+	act->addDefaultInputMapping("KP5");
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionTurnLeft, _("Turn Left"));
+	act->setCustomEngineActionEvent(kPegasusActionLeft);
+	act->addDefaultInputMapping("LEFT");
+	act->addDefaultInputMapping("KP4");
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionTurnRight, _("Turn Right"));
+	act->setCustomEngineActionEvent(kPegasusActionRight);
+	act->addDefaultInputMapping("RIGHT");
+	act->addDefaultInputMapping("KP6");
+	engineKeyMap->addAction(act);
+
+	act = new Action("ENT", _("Action/Select"));
+	act->setCustomEngineActionEvent(kPegasusActionInteract);
+	act->addDefaultInputMapping("SPACE");
+	act->addDefaultInputMapping("RETURN");
+	act->addDefaultInputMapping("KP_ENTER");
+	engineKeyMap->addAction(act);
+
+	// The original also used clear (aka "num lock" on Mac keyboards) here, but it doesn't
+	// work right on most systems. Either SDL or the OS treats num lock specially and the
+	// events don't come as expected. In many cases, the key down event is sent many times
+	// causing the drawer to open and close constantly until pressed again. It only causes
+	// more grief than anything else.
+
+	// The original doesn't use KP7 for inventory, but we're using it as an alternative for
+	// num lock. KP9 is used for the biochip drawer to balance things out.
+
+	act = new Action("TIV", _("Display/Hide Inventory Tray"));
+	act->setCustomEngineActionEvent(kPegasusActionShowInventory);
+	act->addDefaultInputMapping("BACKQUOTE");
+	act->addDefaultInputMapping("KP7");
+	engineKeyMap->addAction(act);
+
+	act = new Action("TBI", _("Display/Hide Biochip Tray"));
+	act->setCustomEngineActionEvent(kPegasusActionShowBiochip);
+	act->addDefaultInputMapping("BACKSPACE");
+	act->addDefaultInputMapping("KP9");
+	act->addDefaultInputMapping("KP_MULTIPLY");
+	engineKeyMap->addAction(act);
+
+	act = new Action("TMA", _("Toggle Center Data Display"));
+	act->setCustomEngineActionEvent(kPegasusActionToggleCenterDisplay);
+	act->addDefaultInputMapping("t");
+	act->addDefaultInputMapping("KP_EQUALS");
+	engineKeyMap->addAction(act);
+
+	act = new Action("TIN", _("Display/Hide Info Screen"));
+	act->setCustomEngineActionEvent(kPegasusActionShowInfoScreen);
+	act->addDefaultInputMapping("i");
+	act->addDefaultInputMapping("KP_DIVIDE");
+	engineKeyMap->addAction(act);
+
+	act = new Action("PM", _("Display/Hide Pause Menu"));
+	act->setCustomEngineActionEvent(kPegasusActionShowPauseMenu);
+	act->addDefaultInputMapping("p");
+	act->addDefaultInputMapping("ESCAPE");
+	engineKeyMap->addAction(act);
+
+	// TODO: Add back Alt to the default mappings
+	// WORKAROUND: I'm also accepting 'e' here since an
+	// alt+click is often intercepted by the OS. 'e' is used as the
+	// easter egg key in Buried in Time and Legacy of Time.
+	act = new Action("WTF", _("???"));
+	act->setCustomEngineActionEvent(kPegasusActionEnableEasterEgg);
+	act->addDefaultInputMapping("e");
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionOpenDebugger, _("Open debugger"));
+	act->setCustomEngineActionEvent(kPegasusActionOpenDebugger);
+	act->addDefaultInputMapping("C+d");
+	engineKeyMap->addAction(act);
+
+	// We support meta where available and control elsewhere
+	act = new Action("SAVE", _("Save Game"));
+	act->setCustomEngineActionEvent(kPegasusActionSaveGameState);
+	act->addDefaultInputMapping("C+s");
+	act->addDefaultInputMapping("M+s");
+	engineKeyMap->addAction(act);
+
+	act = new Action("LOAD", _("Load Game"));
+	act->setCustomEngineActionEvent(kPegasusActionLoadGameState);
+	act->addDefaultInputMapping("C+o"); // o for open (original)
+	act->addDefaultInputMapping("M+o");
+	act->addDefaultInputMapping("C+l"); // l for load (ScummVM terminology)
+	act->addDefaultInputMapping("M+l");
+	engineKeyMap->addAction(act);
 
 	return engineKeyMap;
 }


Commit: 32174c90679c0a9d7234bb5befabdf5aef39a8b4
    https://github.com/scummvm/scummvm/commit/32174c90679c0a9d7234bb5befabdf5aef39a8b4
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
KEYMAPPER: Actions can now be bound to joystick buttons

Changed paths:
    backends/events/default/default-events.cpp
    backends/events/sdl/sdl-events.cpp
    backends/events/sdl/sdl-events.h
    backends/keymapper/hardware-input.cpp
    backends/keymapper/hardware-input.h
    backends/keymapper/input-watcher.cpp
    backends/keymapper/keymap.cpp
    backends/keymapper/keymapper.cpp
    backends/keymapper/standard-actions.cpp
    backends/platform/maemo/maemo.cpp
    backends/platform/sdl/sdl.cpp
    backends/platform/sdl/sdl.h
    common/events.h
    engines/engine.h
    engines/metaengine.cpp
    engines/pegasus/detection.cpp
    engines/pegasus/input.cpp
    engines/pegasus/input.h
    gui/gui-manager.cpp


diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp
index 51b357c..e2f1818 100644
--- a/backends/events/default/default-events.cpp
+++ b/backends/events/default/default-events.cpp
@@ -309,12 +309,14 @@ Common::Keymap *DefaultEventManager::getGlobalKeymap() {
 	Action *act;
 	act = new Action("MENU", _("Menu"));
 	act->addDefaultInputMapping("C+F5");
+	act->addDefaultInputMapping("JOY_START");
 	act->setEvent(EVENT_MAINMENU);
 	globalKeymap->addAction(act);
 
 #ifdef ENABLE_VKEYBD
 	act = new Action("VIRT", _("Display keyboard"));
 	act->addDefaultInputMapping("C+F7");
+	act->addDefaultInputMapping("JOY_BACK");
 	act->setEvent(EVENT_VIRTUAL_KEYBOARD);
 	globalKeymap->addAction(act);
 #endif
diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp
index dae7397..98cb5eb 100644
--- a/backends/events/sdl/sdl-events.cpp
+++ b/backends/events/sdl/sdl-events.cpp
@@ -33,23 +33,9 @@
 #include "engines/engine.h"
 #include "gui/gui-manager.h"
 
-// FIXME move joystick defines out and replace with confile file options
-// we should really allow users to map any key to a joystick button
-
 // #define JOY_INVERT_Y
 #define JOY_XAXIS 0
 #define JOY_YAXIS 1
-// buttons
-#define JOY_BUT_LMOUSE 0
-#define JOY_BUT_RMOUSE 2
-#define JOY_BUT_ESCAPE 3
-#define JOY_BUT_PERIOD 1
-#define JOY_BUT_SPACE 4
-#define JOY_BUT_F5 5
-#ifdef ENABLE_VKEYBD
-#define JOY_BUT_VKEYBOARD 7
-#endif
-
 
 #if SDL_VERSION_ATLEAST(2, 0, 0)
 #define GAMECONTROLLERDB_FILE "gamecontrollerdb.txt"
@@ -881,17 +867,6 @@ void SdlEventSource::closeJoystick() {
 	}
 }
 
-bool SdlEventSource::shouldGenerateMouseEvents() {
-	// Engine doesn't support joystick -> emulate mouse events
-	if (g_engine && !g_engine->hasFeature(Engine::kSupportsJoystick)) {
-		return true;
-	}
-	if (g_gui.isActive()) {
-		return true;
-	}
-	return false;
-}
-
 int SdlEventSource::mapSDLJoystickButtonToOSystem(Uint8 sdlButton) {
 	Common::JoystickButton osystemButtons[] = {
 	    Common::JOYSTICK_BUTTON_A,
@@ -914,91 +889,27 @@ int SdlEventSource::mapSDLJoystickButtonToOSystem(Uint8 sdlButton) {
 }
 
 bool SdlEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {
-	if (!shouldGenerateMouseEvents()) {
-		event.type = Common::EVENT_JOYBUTTON_DOWN;
-		event.joystick.button = mapSDLJoystickButtonToOSystem(ev.jbutton.button);
-		return true;
+	int button = mapSDLJoystickButtonToOSystem(ev.jbutton.button);
+	if (button < 0) {
+		return false;
 	}
 
-	if (ev.jbutton.button == JOY_BUT_LMOUSE) {
-		event.type = Common::EVENT_LBUTTONDOWN;
-		return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
-	} else if (ev.jbutton.button == JOY_BUT_RMOUSE) {
-		event.type = Common::EVENT_RBUTTONDOWN;
-		return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
-	} else {
-		event.type = Common::EVENT_KEYDOWN;
-		switch (ev.jbutton.button) {
-		case JOY_BUT_ESCAPE:
-			event.kbd.keycode = Common::KEYCODE_ESCAPE;
-			event.kbd.ascii = mapKey(SDLK_ESCAPE, (SDLMod)ev.key.keysym.mod, 0);
-			break;
-		case JOY_BUT_PERIOD:
-			event.kbd.keycode = Common::KEYCODE_PERIOD;
-			event.kbd.ascii = mapKey(SDLK_PERIOD, (SDLMod)ev.key.keysym.mod, 0);
-			break;
-		case JOY_BUT_SPACE:
-			event.kbd.keycode = Common::KEYCODE_SPACE;
-			event.kbd.ascii = mapKey(SDLK_SPACE, (SDLMod)ev.key.keysym.mod, 0);
-			break;
-		case JOY_BUT_F5:
-			event.kbd.keycode = Common::KEYCODE_F5;
-			event.kbd.ascii = mapKey(SDLK_F5, (SDLMod)ev.key.keysym.mod, 0);
-			break;
-#ifdef ENABLE_VKEYBD
-		case JOY_BUT_VKEYBOARD: // Toggles virtual keyboard
-			event.type = Common::EVENT_VIRTUAL_KEYBOARD;
-			break;
-#endif
-		default:
-			break;
-		}
-		return true;
-	}
+	event.type = Common::EVENT_JOYBUTTON_DOWN;
+	event.joystick.button = button;
+
+	return true;
 }
 
 bool SdlEventSource::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) {
-	if (!shouldGenerateMouseEvents()) {
-		event.type = Common::EVENT_JOYBUTTON_UP;
-		event.joystick.button = mapSDLJoystickButtonToOSystem(ev.jbutton.button);
-		return true;
+	int button = mapSDLJoystickButtonToOSystem(ev.jbutton.button);
+	if (button < 0) {
+		return false;
 	}
 
-	if (ev.jbutton.button == JOY_BUT_LMOUSE) {
-		event.type = Common::EVENT_LBUTTONUP;
-		return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
-	} else if (ev.jbutton.button == JOY_BUT_RMOUSE) {
-		event.type = Common::EVENT_RBUTTONUP;
-		return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
-	} else {
-		event.type = Common::EVENT_KEYUP;
-		switch (ev.jbutton.button) {
-		case JOY_BUT_ESCAPE:
-			event.kbd.keycode = Common::KEYCODE_ESCAPE;
-			event.kbd.ascii = mapKey(SDLK_ESCAPE, (SDLMod)ev.key.keysym.mod, 0);
-			break;
-		case JOY_BUT_PERIOD:
-			event.kbd.keycode = Common::KEYCODE_PERIOD;
-			event.kbd.ascii = mapKey(SDLK_PERIOD, (SDLMod)ev.key.keysym.mod, 0);
-			break;
-		case JOY_BUT_SPACE:
-			event.kbd.keycode = Common::KEYCODE_SPACE;
-			event.kbd.ascii = mapKey(SDLK_SPACE, (SDLMod)ev.key.keysym.mod, 0);
-			break;
-		case JOY_BUT_F5:
-			event.kbd.keycode = Common::KEYCODE_F5;
-			event.kbd.ascii = mapKey(SDLK_F5, (SDLMod)ev.key.keysym.mod, 0);
-			break;
-#ifdef ENABLE_VKEYBD
-		case JOY_BUT_VKEYBOARD: // Toggles virtual keyboard
-			// Handled in key down
-			break;
-#endif
-		default:
-			break;
-		}
-		return true;
-	}
+	event.type = Common::EVENT_JOYBUTTON_UP;
+	event.joystick.button = button;
+
+	return true;
 }
 
 bool SdlEventSource::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) {
@@ -1036,9 +947,6 @@ bool SdlEventSource::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) {
 	}
 
 bool SdlEventSource::handleJoyHatMotion(SDL_Event &ev, Common::Event &event) {
-	if (shouldGenerateMouseEvents())
-		return false;
-
 	event.type = Common::EVENT_JOYBUTTON_UP;
 	HANDLE_HAT_UP(ev.jhat.value, _lastHatPosition, SDL_HAT_UP, Common::JOYSTICK_BUTTON_DPAD_UP)
 	HANDLE_HAT_UP(ev.jhat.value, _lastHatPosition, SDL_HAT_DOWN, Common::JOYSTICK_BUTTON_DPAD_DOWN)
@@ -1121,102 +1029,20 @@ int SdlEventSource::mapSDLControllerButtonToOSystem(Uint8 sdlButton) {
 }
 
 bool SdlEventSource::handleControllerButton(const SDL_Event &ev, Common::Event &event, bool buttonUp) {
-	using namespace Common;
-
-	struct ControllerEventMapping {
-		EventType normalType;
-		KeyState normalKeystate;
-		EventType modifierType;
-		KeyState modifierKeystate;
-	};
+	int button = mapSDLControllerButtonToOSystem(ev.cbutton.button);
 
-	static const ControllerEventMapping mapping[] = {
-			// SDL_CONTROLLER_BUTTON_A: Left mouse button
-			{ EVENT_LBUTTONDOWN, KeyState(), EVENT_LBUTTONDOWN, KeyState() },
-			// SDL_CONTROLLER_BUTTON_B: Right mouse button
-			{ EVENT_RBUTTONDOWN, KeyState(), EVENT_RBUTTONDOWN, KeyState() },
-			// SDL_CONTROLLER_BUTTON_X: Period (+R_trigger: Space)
-			{ EVENT_KEYDOWN, KeyState(KEYCODE_PERIOD, '.'), EVENT_KEYDOWN, KeyState(KEYCODE_SPACE, ASCII_SPACE) },
-			// SDL_CONTROLLER_BUTTON_Y: Escape (+R_trigger: Return)
-			{ EVENT_KEYDOWN, KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE), EVENT_KEYDOWN, KeyState(KEYCODE_RETURN, ASCII_RETURN) },
-			// SDL_CONTROLLER_BUTTON_BACK: Virtual keyboard (+R_trigger: Predictive Input Dialog)
-#ifdef ENABLE_VKEYBD
-			{ EVENT_VIRTUAL_KEYBOARD, KeyState(), EVENT_PREDICTIVE_DIALOG, KeyState() },
-#else
-			{ EVENT_INVALID, KeyState(), EVENT_PREDICTIVE_DIALOG, KeyState() },
-#endif
-			// SDL_CONTROLLER_BUTTON_GUIDE: Unmapped
-			{ EVENT_INVALID, KeyState(), EVENT_INVALID, KeyState() },
-			// SDL_CONTROLLER_BUTTON_START: ScummVM in game menu
-			{ EVENT_MAINMENU, KeyState(), EVENT_MAINMENU, KeyState() },
-			// SDL_CONTROLLER_BUTTON_LEFTSTICK: Unmapped
-			{ EVENT_INVALID, KeyState(), EVENT_INVALID, KeyState() },
-			// SDL_CONTROLLER_BUTTON_RIGHTSTICK: Unmapped
-			{ EVENT_INVALID, KeyState(), EVENT_INVALID, KeyState() },
-			// SDL_CONTROLLER_BUTTON_LEFTSHOULDER: Game menu
-			{ EVENT_KEYDOWN, KeyState(KEYCODE_F5, ASCII_F5), EVENT_KEYDOWN, KeyState(KEYCODE_F5, ASCII_F5) },
-			// SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: Modifier + Shift
-			{ EVENT_KEYDOWN, KeyState(KEYCODE_INVALID, 0, KBD_SHIFT), EVENT_KEYDOWN, KeyState(KEYCODE_INVALID, 0, 0) },
-			// SDL_CONTROLLER_BUTTON_DPAD_UP: Up (+R_trigger: Up+Right)
-			{ EVENT_KEYDOWN, KeyState(KEYCODE_KP8, 0), EVENT_KEYDOWN, KeyState(KEYCODE_KP9, 0) },
-			// SDL_CONTROLLER_BUTTON_DPAD_DOWN: Down (+R_trigger: Down+Left)
-			{ EVENT_KEYDOWN, KeyState(KEYCODE_KP2, 0), EVENT_KEYDOWN, KeyState(KEYCODE_KP1, 0) },
-			// SDL_CONTROLLER_BUTTON_DPAD_LEFT: Left (+R_trigger: Up+Left)
-			{ EVENT_KEYDOWN, KeyState(KEYCODE_KP4, 0), EVENT_KEYDOWN, KeyState(KEYCODE_KP7, 0) },
-			// SDL_CONTROLLER_BUTTON_DPAD_RIGHT: Right (+R_trigger: Down+Right)
-			{ EVENT_KEYDOWN, KeyState(KEYCODE_KP6, 0), EVENT_KEYDOWN, KeyState(KEYCODE_KP3, 0) }
-	};
-
-	if (!shouldGenerateMouseEvents()) {
-		event.type = buttonUp ? Common::EVENT_JOYBUTTON_UP : Common::EVENT_JOYBUTTON_DOWN;
-		event.joystick.button = mapSDLControllerButtonToOSystem(ev.cbutton.button);
-		if (event.joystick.button == -1)
-				return false;
-
-		return true;
-	}
-
-	if (ev.cbutton.button > SDL_CONTROLLER_BUTTON_DPAD_RIGHT) {
-		warning("Unknown SDL controller button: '%d'", ev.cbutton.button);
+	if (button < 0)
 		return false;
-	}
 
-	if (!_km.modifier) {
-		event.type = mapping[ev.cbutton.button].normalType;
-		event.kbd = mapping[ev.cbutton.button].normalKeystate;
-	} else {
-		event.type = mapping[ev.cbutton.button].modifierType;
-		event.kbd = mapping[ev.cbutton.button].modifierKeystate;
-	}
+	event.type = buttonUp ? Common::EVENT_JOYBUTTON_UP : Common::EVENT_JOYBUTTON_DOWN;
+	event.joystick.button = button;
 
-	// Setting the mouse speed modifier after filling the event structure above
-	// ensures that the shift key events are correctly handled
-	if (ev.cbutton.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER) {
-		// Right shoulder is the modifier button that makes the mouse go slower
-		// and allows access to an extended layout while pressed.
+	if (event.joystick.button == Common::JOYSTICK_BUTTON_RIGHT_SHOULDER) {
+		// Right shoulder is the modifier button that makes the mouse go slower.
 		_km.modifier = !buttonUp;
 	}
 
-	if (event.type == EVENT_LBUTTONDOWN || event.type == EVENT_RBUTTONDOWN) {
-		processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
-	}
-
-	if (buttonUp) {
-		// The event mapping table is for button down events. If we received a button up event,
-		// transform the event type to the corresponding up type.
-		if (event.type == EVENT_KEYDOWN) {
-			event.type = EVENT_KEYUP;
-		} else if (event.type == EVENT_LBUTTONDOWN) {
-			event.type = EVENT_LBUTTONUP;
-		} else if (event.type == EVENT_RBUTTONDOWN) {
-			event.type = EVENT_RBUTTONUP;
-		} else {
-			// Handled in key down
-			event.type = EVENT_INVALID;
-		}
-	}
-
-	return event.type != EVENT_INVALID;
+	return true;
 }
 
 bool SdlEventSource::handleControllerAxisMotion(const SDL_Event &ev, Common::Event &event) {
diff --git a/backends/events/sdl/sdl-events.h b/backends/events/sdl/sdl-events.h
index bf17cc9..f1f2bdd 100644
--- a/backends/events/sdl/sdl-events.h
+++ b/backends/events/sdl/sdl-events.h
@@ -155,8 +155,6 @@ protected:
 	virtual bool handleControllerAxisMotion(const SDL_Event &ev, Common::Event &event);
 #endif
 
-	bool shouldGenerateMouseEvents();
-
 	//@}
 
 	/**
diff --git a/backends/keymapper/hardware-input.cpp b/backends/keymapper/hardware-input.cpp
index 42041b1..195910b 100644
--- a/backends/keymapper/hardware-input.cpp
+++ b/backends/keymapper/hardware-input.cpp
@@ -23,7 +23,9 @@
 #include "backends/keymapper/hardware-input.h"
 
 #include "backends/keymapper/keymapper.h"
+
 #include "common/tokenizer.h"
+#include "common/translation.h"
 
 namespace Common {
 
@@ -215,6 +217,25 @@ const ModifierTableEntry defaultModifiers[] = {
 	{ 0,     nullptr, nullptr }
 };
 
+const HardwareInputTableEntry defaultJoystickButtons[] = {
+    { "JOY_A",              JOYSTICK_BUTTON_A,              _s("Joy A")              },
+    { "JOY_B",              JOYSTICK_BUTTON_B,              _s("Joy B")              },
+    { "JOY_X",              JOYSTICK_BUTTON_X,              _s("Joy X")              },
+    { "JOY_Y",              JOYSTICK_BUTTON_Y,              _s("Joy Y")              },
+    { "JOY_BACK",           JOYSTICK_BUTTON_BACK,           _s("Joy Back")           },
+    { "JOY_GUIDE",          JOYSTICK_BUTTON_GUIDE,          _s("Joy Guide")          },
+    { "JOY_START",          JOYSTICK_BUTTON_START,          _s("Joy Start")          },
+    { "JOY_LEFT_STICK",     JOYSTICK_BUTTON_LEFT_STICK,     _s("Joy Left Stick")     },
+    { "JOY_RIGHT_STICK",    JOYSTICK_BUTTON_RIGHT_STICK,    _s("Joy Right Stick")    },
+    { "JOY_LEFT_SHOULDER",  JOYSTICK_BUTTON_LEFT_SHOULDER,  _s("Joy Left Shoulder")  },
+    { "JOY_RIGHT_SHOULDER", JOYSTICK_BUTTON_RIGHT_SHOULDER, _s("Joy Right Shoulder") },
+    { "JOY_UP",             JOYSTICK_BUTTON_DPAD_UP,        _s("Joy D-pad Up")       },
+    { "JOY_DOWN",           JOYSTICK_BUTTON_DPAD_DOWN,      _s("Joy D-pad Down")     },
+    { "JOY_LEFT",           JOYSTICK_BUTTON_DPAD_LEFT,      _s("Joy D-pad Left")     },
+    { "JOY_RIGHT",          JOYSTICK_BUTTON_DPAD_RIGHT,     _s("Joy D-pad Right")    },
+    { nullptr,              0,                              nullptr                 }
+};
+
 HardwareInputSet::~HardwareInputSet() {
 }
 
@@ -269,7 +290,7 @@ HardwareInput KeyboardHardwareInputSet::findHardwareInput(const String &id) cons
 	}
 
 	const KeyState keystate = KeyState(key->keycode, 0, modifierFlags);
-	return HardwareInput(id, keystate, fullKeyDesc + key->desc);
+	return HardwareInput::createKeyboard(id, keystate, fullKeyDesc + key->desc);
 }
 
 HardwareInput KeyboardHardwareInputSet::findHardwareInput(const Event &event) const {
@@ -301,7 +322,48 @@ HardwareInput KeyboardHardwareInputSet::findHardwareInput(const Event &event) co
 		}
 
 		const KeyState keystate = KeyState(key->keycode, 0, modifierFlags);
-		return HardwareInput(id + key->hwId, keystate, fullKeyDesc + key->desc);
+		return HardwareInput::createKeyboard(id + key->hwId, keystate, fullKeyDesc + key->desc);
+	}
+	default:
+		return HardwareInput();
+	}
+}
+
+JoystickHardwareInputSet::JoystickHardwareInputSet(const HardwareInputTableEntry *buttonEntries) :
+    _buttonEntries(buttonEntries) {
+}
+
+HardwareInput JoystickHardwareInputSet::findHardwareInput(const String &id) const {
+	const HardwareInputTableEntry *hw = nullptr;
+	for (hw = _buttonEntries;  hw->hwId; hw++) {
+		if (id.equals(hw->hwId)) {
+			break;
+		}
+	}
+
+	if (!hw || !hw->hwId) {
+		return HardwareInput();
+	}
+
+	return HardwareInput::createJoystick(hw->hwId, hw->code, hw->desc);
+}
+
+HardwareInput JoystickHardwareInputSet::findHardwareInput(const Event &event) const {
+	switch (event.type) {
+	case EVENT_JOYBUTTON_DOWN:
+	case EVENT_JOYBUTTON_UP: {
+		const HardwareInputTableEntry *hw = nullptr;
+		for (hw = _buttonEntries;  hw->hwId; hw++) {
+			if (event.joystick.button == hw->code) {
+				break;
+			}
+		}
+
+		if (!hw || !hw->hwId) {
+			return HardwareInput();
+		}
+
+		return HardwareInput::createJoystick(hw->hwId, hw->code, hw->desc);
 	}
 	default:
 		return HardwareInput();
@@ -325,7 +387,7 @@ HardwareInput CustomHardwareInputSet::findHardwareInput(const String &id) const
 		return HardwareInput();
 	}
 
-	return HardwareInput(hw->hwId, hw->code, hw->desc);
+	return HardwareInput::createCustom(hw->hwId, hw->code, hw->desc);
 }
 
 HardwareInput CustomHardwareInputSet::findHardwareInput(const Event &event) const {
@@ -342,7 +404,7 @@ HardwareInput CustomHardwareInputSet::findHardwareInput(const Event &event) cons
 			return HardwareInput();
 		}
 
-		return HardwareInput(hw->hwId, hw->code, hw->desc);
+		return HardwareInput::createCustom(hw->hwId, hw->code, hw->desc);
 	}
 	default:
 		return HardwareInput();
@@ -377,4 +439,8 @@ HardwareInput CompositeHardwareInputSet::findHardwareInput(const Event &event) c
 	return HardwareInput();
 }
 
+void CompositeHardwareInputSet::addHardwareInputSet(HardwareInputSet *hardwareInputSet) {
+	_inputSets.push_back(hardwareInputSet);
+}
+
 } //namespace Common
diff --git a/backends/keymapper/hardware-input.h b/backends/keymapper/hardware-input.h
index d2055dc..d6e3f7d 100644
--- a/backends/keymapper/hardware-input.h
+++ b/backends/keymapper/hardware-input.h
@@ -38,9 +38,11 @@ enum HardwareInputType {
 	/** Empty / invalid input type */
 	kHardwareInputTypeInvalid,
 	/** Input that sends single events */
-	kHardwareInputTypeGeneric,
-	/** Input that usually send -up and -down events */
-	kHardwareInputTypeKeyboard
+	kHardwareInputTypeCustom,
+	/** Keyboard input that sends -up and -down events */
+	kHardwareInputTypeKeyboard,
+	/** Joystick input that sends -up and -down events */
+	kHardwareInputTypeJoystick
 };
 
 /**
@@ -73,11 +75,33 @@ struct HardwareInput {
 	HardwareInput()
 		: inputCode(0), type(kHardwareInputTypeInvalid) { }
 
-	HardwareInput(const String &i, HardwareInputCode ic, const String &desc)
-		: id(i), inputCode(ic), description(desc), type(kHardwareInputTypeGeneric) { }
-
-	HardwareInput(const String &i, KeyState ky, const String &desc)
-		: id(i), inputCode(0), key(ky), description(desc), type(kHardwareInputTypeKeyboard) { }
+	static HardwareInput createCustom(const String &i, HardwareInputCode ic, const String &desc) {
+		HardwareInput hardwareInput;
+		hardwareInput.id = i;
+		hardwareInput.description = desc;
+		hardwareInput.type = kHardwareInputTypeCustom;
+		hardwareInput.inputCode = ic;
+		return hardwareInput;
+	}
+
+	static HardwareInput createKeyboard(const String &i, KeyState ky, const String &desc) {
+		HardwareInput hardwareInput;
+		hardwareInput.id = i;
+		hardwareInput.description = desc;
+		hardwareInput.type = kHardwareInputTypeKeyboard;
+		hardwareInput.inputCode = 0;
+		hardwareInput.key = ky;
+		return hardwareInput;
+	}
+
+	static HardwareInput createJoystick(const String &i, uint8 button, const String &desc) {
+		HardwareInput hardwareInput;
+		hardwareInput.id = i;
+		hardwareInput.description = desc;
+		hardwareInput.type = kHardwareInputTypeJoystick;
+		hardwareInput.inputCode = button;
+		return hardwareInput;
+	}
 };
 
 /**
@@ -153,6 +177,21 @@ private:
 };
 
 /**
+ * A joystick input device
+ */
+class JoystickHardwareInputSet : public HardwareInputSet {
+public:
+	JoystickHardwareInputSet(const HardwareInputTableEntry *buttonEntries);
+
+	// HardwareInputSet API
+	HardwareInput findHardwareInput(const String &id) const override;
+	HardwareInput findHardwareInput(const Event &event) const override;
+
+private:
+	const HardwareInputTableEntry *_buttonEntries;
+};
+
+/**
  * A custom backend input device
  *
  * @todo This is currently unused. Perhaps it should be removed.
@@ -197,6 +236,9 @@ extern const KeyTableEntry defaultKeys[];
 /** A standard set of keyboard modifiers */
 extern const ModifierTableEntry defaultModifiers[];
 
+/** A standard set of joystick buttons based on the ScummVM event model */
+extern const HardwareInputTableEntry defaultJoystickButtons[];
+
 } // End of namespace Common
 
 #endif // #ifndef COMMON_HARDWARE_KEY_H
diff --git a/backends/keymapper/input-watcher.cpp b/backends/keymapper/input-watcher.cpp
index 90b0218..236cfdc 100644
--- a/backends/keymapper/input-watcher.cpp
+++ b/backends/keymapper/input-watcher.cpp
@@ -59,8 +59,10 @@ bool InputWatcher::notifyEvent(const Event &event) {
 
 	switch (event.type) {
 		case EVENT_KEYDOWN:
+		case EVENT_JOYBUTTON_DOWN:
 			return true;
 		case EVENT_KEYUP:
+		case EVENT_JOYBUTTON_UP:
 		case EVENT_CUSTOM_BACKEND_HARDWARE:
 			_hwInput = _keymapper->findHardwareInput(event);
 			if (_hwInput.type != kHardwareInputTypeInvalid) {
diff --git a/backends/keymapper/keymap.cpp b/backends/keymapper/keymap.cpp
index 5a306db..228522e 100644
--- a/backends/keymapper/keymap.cpp
+++ b/backends/keymapper/keymap.cpp
@@ -115,11 +115,16 @@ Keymap::ActionArray Keymap::getMappedActions(const Event &event) const {
 	switch (event.type) {
 	case EVENT_KEYDOWN:
 	case EVENT_KEYUP: {
-		HardwareInput hardwareInput("", event.kbd, "");
+		HardwareInput hardwareInput = HardwareInput::createKeyboard("", event.kbd, "");
+		return _hwActionMap[hardwareInput];
+	}
+	case EVENT_JOYBUTTON_DOWN:
+	case EVENT_JOYBUTTON_UP: {
+		HardwareInput hardwareInput = HardwareInput::createJoystick("", event.joystick.button, "");
 		return _hwActionMap[hardwareInput];
 	}
 	case EVENT_CUSTOM_BACKEND_HARDWARE: {
-		HardwareInput hardwareInput("", event.customType, "");
+		HardwareInput hardwareInput = HardwareInput::createCustom("", event.customType, "");
 		return _hwActionMap[hardwareInput];
 	}
 	default:
diff --git a/backends/keymapper/keymapper.cpp b/backends/keymapper/keymapper.cpp
index 46202c6..5214d09 100644
--- a/backends/keymapper/keymapper.cpp
+++ b/backends/keymapper/keymapper.cpp
@@ -191,7 +191,7 @@ List<Event> Keymapper::mapEvent(const Event &ev) {
 Keymapper::IncomingEventType Keymapper::convertToIncomingEventType(const Event &ev) const {
 	if (ev.type == EVENT_CUSTOM_BACKEND_HARDWARE) {
 		return kIncomingEventInstant;
-	} else if (ev.type == EVENT_KEYDOWN) {
+	} else if (ev.type == EVENT_KEYDOWN || ev.type == EVENT_JOYBUTTON_DOWN) {
 		return kIncomingEventStart;
 	} else {
 		return kIncomingEventEnd;
@@ -242,6 +242,9 @@ EventType Keymapper::convertStartToEnd(EventType type) {
 	case EVENT_MBUTTONDOWN:
 		result = EVENT_MBUTTONUP;
 		break;
+	case EVENT_JOYBUTTON_DOWN:
+		result = EVENT_JOYBUTTON_UP;
+		break;
 	case EVENT_CUSTOM_BACKEND_ACTION_START:
 		result = EVENT_CUSTOM_BACKEND_ACTION_END;
 		break;
@@ -282,12 +285,6 @@ void Keymapper::hardcodedEventMapping(Event ev) {
 		}
 	}
 #endif
-
-	if (ev.type == EVENT_JOYBUTTON_DOWN) {
-		if (ev.joystick.button == JOYSTICK_BUTTON_START || ev.joystick.button == JOYSTICK_BUTTON_GUIDE) {
-			ev.type = EVENT_MAINMENU;
-		}
-	}
 }
 
 void DelayedEventSource::scheduleEvent(const Event &ev, uint32 delayMillis) {
diff --git a/backends/keymapper/standard-actions.cpp b/backends/keymapper/standard-actions.cpp
index 006a8e5..21b0d62 100644
--- a/backends/keymapper/standard-actions.cpp
+++ b/backends/keymapper/standard-actions.cpp
@@ -24,7 +24,7 @@
 
 namespace Common {
 
-const char *kStandardActionInteract      = "INTCT";
+const char *kStandardActionInteract      = "INTRCT";
 const char *kStandardActionSkip          = "SKIP";
 const char *kStandardActionPause         = "PAUSE";
 const char *kStandardActionMoveForward   = "FWD";
diff --git a/backends/platform/maemo/maemo.cpp b/backends/platform/maemo/maemo.cpp
index 517b3ce..ef44b58 100644
--- a/backends/platform/maemo/maemo.cpp
+++ b/backends/platform/maemo/maemo.cpp
@@ -184,9 +184,9 @@ static const Common::KeyTableEntry maemoKeys[] = {
 };
 
 Common::HardwareInputSet *OSystem_SDL_Maemo::getHardwareInputSet() {
-	Common::CompositeHardwareInputSet inputSet = new Common::CompositeHardwareInputSet();
-	inputSet->addHardwareInputSet(new Common::KeyboardHardwareInputSet(maemoKeys, defaultModifiers));
-	inputSet->addHardwareInputSet(new Common::KeyboardHardwareInputSet(defaultKeys, defaultModifiers));
+	Common::CompositeHardwareInputSet *inputSet = new Common::CompositeHardwareInputSet();
+	inputSet->addHardwareInputSet(new Common::KeyboardHardwareInputSet(maemoKeys, Common::defaultModifiers));
+	inputSet->addHardwareInputSet(new Common::KeyboardHardwareInputSet(Common::defaultKeys, Common::defaultModifiers));
 
 	return inputSet;
 }
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 9ed28ea..309d977 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -41,6 +41,7 @@
 
 #include "backends/events/default/default-events.h"
 #include "backends/events/sdl/sdl-events.h"
+#include "backends/keymapper/hardware-input.h"
 #include "backends/mutex/sdl/sdl-mutex.h"
 #include "backends/timer/sdl/sdl-timer.h"
 #include "backends/graphics/surfacesdl/surfacesdl-graphics.h"
@@ -398,6 +399,20 @@ Common::KeymapArray OSystem_SDL::getGlobalKeymaps() {
 	return globalMaps;
 }
 
+Common::HardwareInputSet *OSystem_SDL::getHardwareInputSet() {
+	using namespace Common;
+
+	CompositeHardwareInputSet *inputSet = new CompositeHardwareInputSet();
+	inputSet->addHardwareInputSet(new KeyboardHardwareInputSet(defaultKeys, defaultModifiers));
+
+	bool joystickSupportEnabled = ConfMan.getInt("joystick_num") >= 0;
+	if (joystickSupportEnabled) {
+		inputSet->addHardwareInputSet(new JoystickHardwareInputSet(defaultJoystickButtons));
+	}
+
+	return inputSet;
+}
+
 void OSystem_SDL::logMessage(LogMessageType::Type type, const char *message) {
 	// First log to stdout/stderr
 	FILE *output = 0;
diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h
index bd7b538..1cee826 100644
--- a/backends/platform/sdl/sdl.h
+++ b/backends/platform/sdl/sdl.h
@@ -64,6 +64,7 @@ public:
 	virtual void quit();
 	virtual void fatalError();
 	Common::KeymapArray getGlobalKeymaps() override;
+	Common::HardwareInputSet *getHardwareInputSet() override;
 
 	// Logging
 	virtual void logMessage(LogMessageType::Type type, const char *message);
diff --git a/common/events.h b/common/events.h
index 3e4d046..fdf4f01 100644
--- a/common/events.h
+++ b/common/events.h
@@ -111,7 +111,7 @@ struct JoystickState {
 	 * Some of the button indices match well-known game controller
 	 * buttons. See JoystickButton.
 	 */
-	int8 button;
+	uint8 button;
 
 	JoystickState() : axis(0), position(0), button(0) {}
 };
diff --git a/engines/engine.h b/engines/engine.h
index db8cc02..6f2c7fd 100644
--- a/engines/engine.h
+++ b/engines/engine.h
@@ -132,15 +132,7 @@ public:
 		 * If this feature is supported, then the corresponding MetaEngine *must*
 		 * support the kSupportsListSaves feature.
 		 */
-		kSupportsSavingDuringRuntime,
-
-		/**
-		 * Engine must receive joystick events because the game uses them.
-		 * For engines which have not this feature, joystick events are converted
-		 * to mouse events.
-		 */
-		kSupportsJoystick
-
+		kSupportsSavingDuringRuntime
 	};
 
 
diff --git a/engines/metaengine.cpp b/engines/metaengine.cpp
index 060e4d5..8be0ffa 100644
--- a/engines/metaengine.cpp
+++ b/engines/metaengine.cpp
@@ -50,27 +50,13 @@ const char *MetaEngine::getSavegamePattern(const char *target) const {
 Common::Keymap *MetaEngine::initKeymap(const char *target) const {
 	using namespace Common;
 
-	Keymap *const engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "engine-default");
-
-	// Since the game has multiple built-in keys for each of these anyway,
-	// this just attempts to remap one of them.
-	const KeyActionEntry keyActionEntries[] = {
-		{ "PAUS", KeyState(KEYCODE_SPACE, ' ', 0),           "SPACE",  _("Pause")     },
-		{ "SKCT", KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE, 0), "ESCAPE", _("Skip")      },
-		{ "SKLI", KeyState(KEYCODE_PERIOD, '.', 0),          "PERIOD", _("Skip line") }
-	};
-
-	for (uint i = 0; i < ARRAYSIZE(keyActionEntries); i++) {
-		Action *const act = new Action(keyActionEntries[i].id, keyActionEntries[i].description);
-		act->setKeyEvent(keyActionEntries[i].ks);
-		act->addDefaultInputMapping(keyActionEntries[i].defaultHwId);
-		engineKeyMap->addAction(act);
-	}
+	Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "engine-default");
 
 	Action *act;
 
 	act = new Action("LCLK", _("Left Click"));
 	act->setLeftClickEvent();
+	act->addDefaultInputMapping("JOY_A");
 	engineKeyMap->addAction(act);
 
 	act = new Action("MCLK", _("Middle Click"));
@@ -79,6 +65,57 @@ Common::Keymap *MetaEngine::initKeymap(const char *target) const {
 
 	act = new Action("RCLK", _("Right Click"));
 	act->setRightClickEvent();
+	act->addDefaultInputMapping("JOY_B");
+	engineKeyMap->addAction(act);
+
+	act = new Action("PAUS", _("Pause"));
+	act->setKeyEvent(KeyState(KEYCODE_SPACE, ' '));
+	act->addDefaultInputMapping("SPACE");
+	engineKeyMap->addAction(act);
+
+	act = new Action("MNU", _("Game menu"));
+	act->setKeyEvent(KeyState(KEYCODE_F5, ASCII_F5));
+	act->addDefaultInputMapping("F5");
+	act->addDefaultInputMapping("JOY_LEFT_SHOULDER");
+	engineKeyMap->addAction(act);
+
+	act = new Action("SKCT", _("Skip"));
+	act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE));
+	act->addDefaultInputMapping("ESCAPE");
+	engineKeyMap->addAction(act);
+
+	act = new Action("SKLI", _("Skip line"));
+	act->setKeyEvent(KeyState(KEYCODE_PERIOD, '.'));
+	act->addDefaultInputMapping("PERIOD");
+	engineKeyMap->addAction(act);
+
+	act = new Action("PIND", _("Predictive input dialog"));
+	act->setEvent(EVENT_PREDICTIVE_DIALOG);
+	engineKeyMap->addAction(act);
+
+	act = new Action("RETURN", _("Confirm"));
+	act->setKeyEvent(KeyState(KEYCODE_RETURN, ASCII_RETURN));
+	act->addDefaultInputMapping("RETURN");
+	engineKeyMap->addAction(act);
+
+	act = new Action("UP", _("Up"));
+	act->setKeyEvent(KEYCODE_KP8);
+	act->addDefaultInputMapping("JOY_UP");
+	engineKeyMap->addAction(act);
+
+	act = new Action("DOWN", _("Down"));
+	act->setKeyEvent(KEYCODE_KP2);
+	act->addDefaultInputMapping("JOY_DOWN");
+	engineKeyMap->addAction(act);
+
+	act = new Action("LEFT", _("Left"));
+	act->setKeyEvent(KEYCODE_KP4);
+	act->addDefaultInputMapping("JOY_LEFT");
+	engineKeyMap->addAction(act);
+
+	act = new Action("RIGHT", _("Right"));
+	act->setKeyEvent(KEYCODE_KP6);
+	act->addDefaultInputMapping("JOY_RIGHT");
 	engineKeyMap->addAction(act);
 
 	return engineKeyMap;
diff --git a/engines/pegasus/detection.cpp b/engines/pegasus/detection.cpp
index 2a23a3c..5d723d4 100644
--- a/engines/pegasus/detection.cpp
+++ b/engines/pegasus/detection.cpp
@@ -43,8 +43,7 @@ bool PegasusEngine::hasFeature(EngineFeature f) const {
 	return
 		(f == kSupportsRTL)
 		|| (f == kSupportsLoadingDuringRuntime)
-		|| (f == kSupportsSavingDuringRuntime)
-		|| (f == kSupportsJoystick);
+		|| (f == kSupportsSavingDuringRuntime);
 }
 
 bool PegasusEngine::isDemo() const {
diff --git a/engines/pegasus/input.cpp b/engines/pegasus/input.cpp
index 42edf35..bac3c2f 100644
--- a/engines/pegasus/input.cpp
+++ b/engines/pegasus/input.cpp
@@ -136,37 +136,6 @@ void InputDeviceManager::waitInput(const InputBits filter) {
 	}
 }
 
-PegasusAction InputDeviceManager::convertJoystickToKey(uint joybutton) {
-	switch (joybutton) {
-	case Common::JOYSTICK_BUTTON_A:
-		return kPegasusActionInteract;
-	case Common::JOYSTICK_BUTTON_B:
-		// nothing
-		break;
-	case Common::JOYSTICK_BUTTON_X:
-		return kPegasusActionShowInfoScreen;
-	case Common::JOYSTICK_BUTTON_Y:
-		return kPegasusActionToggleCenterDisplay;
-	case Common::JOYSTICK_BUTTON_LEFT_SHOULDER:
-		return kPegasusActionShowInventory;
-	case Common::JOYSTICK_BUTTON_RIGHT_SHOULDER:
-		return kPegasusActionShowBiochip;
-	case Common::JOYSTICK_BUTTON_BACK:
-		return kPegasusActionShowPauseMenu;
-	case Common::JOYSTICK_BUTTON_DPAD_UP:
-		return kPegasusActionUp;
-	case Common::JOYSTICK_BUTTON_DPAD_DOWN:
-		return kPegasusActionDown;
-	case Common::JOYSTICK_BUTTON_DPAD_LEFT:
-		return kPegasusActionLeft;
-	case Common::JOYSTICK_BUTTON_DPAD_RIGHT:
-		return kPegasusActionRight;
-	default:
-		break;
-	}
-	return kPegasusActionNone;
-}
-
 bool InputDeviceManager::notifyEvent(const Common::Event &event) {
 	if (GUI::GuiManager::instance().isActive()) {
 		// For some reason, the engine hooks in the event system using an EventObserver.
@@ -201,16 +170,6 @@ bool InputDeviceManager::notifyEvent(const Common::Event &event) {
 		if (event.customType != kPegasusActionNone && event.customType < kPegasusActionCount)
 			_keysDown[event.customType] = false;
 		break;
-	case Common::EVENT_JOYAXIS_MOTION:
-		break;
-	case Common::EVENT_JOYBUTTON_DOWN:
-		if (convertJoystickToKey(event.joystick.button) != kPegasusActionNone)
-			_keysDown[convertJoystickToKey(event.joystick.button)] = true;
-		break;
-	case Common::EVENT_JOYBUTTON_UP:
-		if (convertJoystickToKey(event.joystick.button) != kPegasusActionNone)
-			_keysDown[convertJoystickToKey(event.joystick.button)] = false;
-		break;
 	default:
 		break;
 	}
diff --git a/engines/pegasus/input.h b/engines/pegasus/input.h
index f9ec00a..b5d4d5e 100644
--- a/engines/pegasus/input.h
+++ b/engines/pegasus/input.h
@@ -71,8 +71,6 @@ public:
 
 	void pumpEvents();
 
-	PegasusAction convertJoystickToKey(uint joybutton);
-
 protected:
 	friend class Common::Singleton<SingletonBaseType>;
 
diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp
index 0f15023..9114e17 100644
--- a/gui/gui-manager.cpp
+++ b/gui/gui-manager.cpp
@@ -33,6 +33,7 @@
 #include "backends/keymapper/action.h"
 #include "backends/keymapper/keymap.h"
 #include "backends/keymapper/keymapper.h"
+#include "backends/keymapper/standard-actions.h"
 
 #include "gui/gui-manager.h"
 #include "gui/dialog.h"
@@ -116,8 +117,14 @@ Common::Keymap *GuiManager::getKeymap() const {
 
 	Action *act;
 
+	act = new Action(Common::kStandardActionInteract, _("Interact"));
+	act->addDefaultInputMapping("JOY_A");
+	act->setLeftClickEvent();
+	guiMap->addAction(act);
+
 	act = new Action("CLOS", _("Close"));
 	act->addDefaultInputMapping("ESCAPE");
+	act->addDefaultInputMapping("JOY_Y");
 	act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE, 0));
 	guiMap->addAction(act);
 


Commit: 376a77e735acb1001e75ed0f6dc87de086842a16
    https://github.com/scummvm/scummvm/commit/376a77e735acb1001e75ed0f6dc87de086842a16
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
PEGASUS: Add default joystick action bindings

Changed paths:
    engines/pegasus/input.cpp
    engines/pegasus/pegasus.cpp


diff --git a/engines/pegasus/input.cpp b/engines/pegasus/input.cpp
index bac3c2f..97db74e 100644
--- a/engines/pegasus/input.cpp
+++ b/engines/pegasus/input.cpp
@@ -95,13 +95,6 @@ void InputDeviceManager::getInput(Input &input, const InputBits filter) {
 	if (_keysDown[kPegasusActionShowBiochip])
 		currentBits |= (kRawButtonDown << kRightFireButtonShift);
 
-	// Update mouse button state
-	// Note that we don't use EVENT_LBUTTONUP/EVENT_LBUTTONDOWN because
-	// they do not show if the button is being held down. We're treating
-	// both mouse buttons as the same for ease of use.
-	if (g_system->getEventManager()->getButtonState() != 0)
-		currentBits |= (kRawButtonDown << kTwoButtonShift);
-
 	// Update the mouse position too
 	input.setInputLocation(g_system->getEventManager()->getMousePos());
 
diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp
index 98f29d2..524fec4 100644
--- a/engines/pegasus/pegasus.cpp
+++ b/engines/pegasus/pegasus.cpp
@@ -2500,24 +2500,28 @@ Common::Keymap *PegasusEngine::initKeymap() {
 	act->setCustomEngineActionEvent(kPegasusActionUp);
 	act->addDefaultInputMapping("UP");
 	act->addDefaultInputMapping("KP8");
+	act->addDefaultInputMapping("JOY_UP");
 	engineKeyMap->addAction(act);
 
 	act = new Action(kStandardActionMoveBackwards, _("Down/Zoom Out"));
 	act->setCustomEngineActionEvent(kPegasusActionDown);
 	act->addDefaultInputMapping("DOWN");
 	act->addDefaultInputMapping("KP5");
+	act->addDefaultInputMapping("JOY_DOWN");
 	engineKeyMap->addAction(act);
 
 	act = new Action(kStandardActionTurnLeft, _("Turn Left"));
 	act->setCustomEngineActionEvent(kPegasusActionLeft);
 	act->addDefaultInputMapping("LEFT");
 	act->addDefaultInputMapping("KP4");
+	act->addDefaultInputMapping("JOY_LEFT");
 	engineKeyMap->addAction(act);
 
 	act = new Action(kStandardActionTurnRight, _("Turn Right"));
 	act->setCustomEngineActionEvent(kPegasusActionRight);
 	act->addDefaultInputMapping("RIGHT");
 	act->addDefaultInputMapping("KP6");
+	act->addDefaultInputMapping("JOY_RIGHT");
 	engineKeyMap->addAction(act);
 
 	act = new Action("ENT", _("Action/Select"));
@@ -2525,6 +2529,10 @@ Common::Keymap *PegasusEngine::initKeymap() {
 	act->addDefaultInputMapping("SPACE");
 	act->addDefaultInputMapping("RETURN");
 	act->addDefaultInputMapping("KP_ENTER");
+	act->addDefaultInputMapping("JOY_A");
+	// We're treating both mouse buttons as the same for ease of use.
+	act->addDefaultInputMapping("MOUSE_LEFT");
+	act->addDefaultInputMapping("MOUSE_RIGHT");
 	engineKeyMap->addAction(act);
 
 	// The original also used clear (aka "num lock" on Mac keyboards) here, but it doesn't
@@ -2540,6 +2548,7 @@ Common::Keymap *PegasusEngine::initKeymap() {
 	act->setCustomEngineActionEvent(kPegasusActionShowInventory);
 	act->addDefaultInputMapping("BACKQUOTE");
 	act->addDefaultInputMapping("KP7");
+	act->addDefaultInputMapping("JOY_LEFT_SHOULDER");
 	engineKeyMap->addAction(act);
 
 	act = new Action("TBI", _("Display/Hide Biochip Tray"));
@@ -2547,24 +2556,28 @@ Common::Keymap *PegasusEngine::initKeymap() {
 	act->addDefaultInputMapping("BACKSPACE");
 	act->addDefaultInputMapping("KP9");
 	act->addDefaultInputMapping("KP_MULTIPLY");
+	act->addDefaultInputMapping("JOY_RIGHT_SHOULDER");
 	engineKeyMap->addAction(act);
 
 	act = new Action("TMA", _("Toggle Center Data Display"));
 	act->setCustomEngineActionEvent(kPegasusActionToggleCenterDisplay);
 	act->addDefaultInputMapping("t");
 	act->addDefaultInputMapping("KP_EQUALS");
+	act->addDefaultInputMapping("JOY_Y");
 	engineKeyMap->addAction(act);
 
 	act = new Action("TIN", _("Display/Hide Info Screen"));
 	act->setCustomEngineActionEvent(kPegasusActionShowInfoScreen);
 	act->addDefaultInputMapping("i");
 	act->addDefaultInputMapping("KP_DIVIDE");
+	act->addDefaultInputMapping("JOY_X");
 	engineKeyMap->addAction(act);
 
 	act = new Action("PM", _("Display/Hide Pause Menu"));
 	act->setCustomEngineActionEvent(kPegasusActionShowPauseMenu);
 	act->addDefaultInputMapping("p");
 	act->addDefaultInputMapping("ESCAPE");
+	act->addDefaultInputMapping("JOY_BACK");
 	engineKeyMap->addAction(act);
 
 	// TODO: Add back Alt to the default mappings


Commit: 426867f4bc2820b5bec0fb2ba0e805424c8b6ed9
    https://github.com/scummvm/scummvm/commit/426867f4bc2820b5bec0fb2ba0e805424c8b6ed9
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
KEYMAPPER: Give human readable descriptions to the keymaps

Changed paths:
    backends/events/default/default-events.cpp
    backends/graphics/sdl/sdl-graphics.cpp
    backends/keymapper/keymap.cpp
    backends/keymapper/keymap.h
    backends/keymapper/keymapper.cpp
    backends/keymapper/keymapper.h
    backends/keymapper/remap-widget.cpp
    backends/platform/maemo/maemo.cpp
    engines/kyra/engine/eobcommon.cpp
    engines/kyra/engine/lol.cpp
    engines/metaengine.cpp
    engines/mohawk/riven.cpp
    engines/pegasus/pegasus.cpp
    gui/gui-manager.cpp


diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp
index e2f1818..f9fcafa 100644
--- a/backends/events/default/default-events.cpp
+++ b/backends/events/default/default-events.cpp
@@ -304,7 +304,7 @@ Common::Keymap *DefaultEventManager::getGlobalKeymap() {
 	using namespace Common;
 
 	// Now create the global keymap
-	Keymap *globalKeymap = new Keymap(Keymap::kKeymapTypeGlobal, kGlobalKeymapName);
+	Keymap *globalKeymap = new Keymap(Keymap::kKeymapTypeGlobal, kGlobalKeymapName, _("Global"));
 
 	Action *act;
 	act = new Action("MENU", _("Menu"));
diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp
index 2c68c0f..99a7863 100644
--- a/backends/graphics/sdl/sdl-graphics.cpp
+++ b/backends/graphics/sdl/sdl-graphics.cpp
@@ -355,7 +355,7 @@ void SdlGraphicsManager::toggleFullScreen() {
 Common::Keymap *SdlGraphicsManager::getKeymap() {
 	using namespace Common;
 
-	Keymap *keymap = new Keymap(Keymap::kKeymapTypeGlobal, "sdl-graphics");
+	Keymap *keymap = new Keymap(Keymap::kKeymapTypeGlobal, "sdl-graphics", _("Graphics"));
 	Action *act;
 
 	if (hasFeature(OSystem::kFeatureFullscreenMode)) {
diff --git a/backends/keymapper/keymap.cpp b/backends/keymapper/keymap.cpp
index 228522e..51f6207 100644
--- a/backends/keymapper/keymap.cpp
+++ b/backends/keymapper/keymap.cpp
@@ -33,11 +33,12 @@
 
 namespace Common {
 
-Keymap::Keymap(KeymapType type, const String &name) :
+Keymap::Keymap(KeymapType type, const String &id, const String &description) :
 		_type(type),
-		_name(name),
-		_configDomain(nullptr),
+		_id(id),
+		_description(description),
 		_enabled(true),
+		_configDomain(nullptr),
 		_hardwareInputSet(nullptr),
 		_backendDefaultBindings(nullptr) {
 
@@ -149,7 +150,7 @@ void Keymap::registerBackendDefaultMappings() {
 
 	for (ActionArray::const_iterator it = _actions.begin(); it != _actions.end(); ++it) {
 		Action *action = *it;
-		Common::String defaultHwId = _backendDefaultBindings->getDefaultBinding(_name, action->id);
+		Common::String defaultHwId = _backendDefaultBindings->getDefaultBinding(_id, action->id);
 
 		if (!defaultHwId.empty()) {
 			action->addDefaultInputMapping(defaultHwId);
@@ -176,7 +177,7 @@ void Keymap::loadMappings() {
 		registerBackendDefaultMappings();
 	}
 
-	String prefix = KEYMAP_KEY_PREFIX + _name + "_";
+	String prefix = KEYMAP_KEY_PREFIX + _id + "_";
 
 	_hwActionMap.clear();
 	for (ActionArray::const_iterator it = _actions.begin(); it != _actions.end(); ++it) {
@@ -222,7 +223,7 @@ void Keymap::saveMappings() {
 	if (!_configDomain)
 		return;
 
-	String prefix = KEYMAP_KEY_PREFIX + _name + "_";
+	String prefix = KEYMAP_KEY_PREFIX + _id + "_";
 
 	for (ActionArray::const_iterator it = _actions.begin(); it != _actions.end(); it++) {
 		Action *action = *it;
diff --git a/backends/keymapper/keymap.h b/backends/keymapper/keymap.h
index 7abc439..22dbf14 100644
--- a/backends/keymapper/keymap.h
+++ b/backends/keymapper/keymap.h
@@ -73,7 +73,7 @@ public:
 
 	typedef Array<Action *> ActionArray;
 
-	Keymap(KeymapType type, const String &name);
+	Keymap(KeymapType type, const String &id, const String &description);
 	~Keymap();
 	void setConfigDomain(ConfigManager::Domain *configDomain);
 	void setHardwareInputs(HardwareInputSet *hardwareInputSet);
@@ -139,7 +139,8 @@ public:
 	 */
 	void saveMappings();
 
-	const String &getName() const { return _name; }
+	const String &getId() const { return _id; }
+	const String &getDescription() const { return _description; }
 	KeymapType getType() const { return _type; }
 
 	/**
@@ -158,7 +159,8 @@ private:
 	typedef HashMap<HardwareInput, ActionArray, Event_Hash, Event_EqualTo> HardwareActionMap;
 
 	KeymapType _type;
-	String _name;
+	String _id;
+	String _description;
 
 	bool _enabled;
 
diff --git a/backends/keymapper/keymapper.cpp b/backends/keymapper/keymapper.cpp
index 5214d09..acd1e64 100644
--- a/backends/keymapper/keymapper.cpp
+++ b/backends/keymapper/keymapper.cpp
@@ -95,7 +95,7 @@ void Keymapper::addGameKeymap(Keymap *keymap) {
 
 void Keymapper::initKeymap(Keymap *keymap, ConfigManager::Domain *domain) {
 	if (!_hardwareInputs) {
-		warning("No hardware inputs were registered yet (%s)", keymap->getName().c_str());
+		warning("No hardware inputs were registered yet (%s)", keymap->getId().c_str());
 		return;
 	}
 
@@ -118,9 +118,9 @@ void Keymapper::cleanupGameKeymaps() {
 	}
 }
 
-Keymap *Keymapper::getKeymap(const String &name) {
+Keymap *Keymapper::getKeymap(const String &id) const {
 	for (KeymapArray::const_iterator it = _keymaps.begin(); it != _keymaps.end(); it++) {
-		if ((*it)->getName() == name) {
+		if ((*it)->getId() == id) {
 			return *it;
 		}
 	}
@@ -160,7 +160,7 @@ List<Event> Keymapper::mapEvent(const Event &ev) {
 			continue; // Ignore GUI keymaps while in game and vice versa
 		}
 
-		debug(5, "Keymapper::mapKey keymap: %s", _keymaps[i]->getName().c_str());
+		debug(5, "Keymapper::mapKey keymap: %s", _keymaps[i]->getId().c_str());
 
 		const Keymap::ActionArray &actions = _keymaps[i]->getMappedActions(ev);
 		for (Keymap::ActionArray::const_iterator it = actions.begin(); it != actions.end(); it++) {
diff --git a/backends/keymapper/keymapper.h b/backends/keymapper/keymapper.h
index 9e3e3f7..b1e1c76 100644
--- a/backends/keymapper/keymapper.h
+++ b/backends/keymapper/keymapper.h
@@ -92,9 +92,9 @@ public:
 	/**
 	 * Obtain a keymap of the given name from the keymapper.
 	 * Game keymaps have priority over global keymaps
-	 * @param name		name of the keymap to return
+	 * @param id		name of the keymap to return
 	 */
-	Keymap *getKeymap(const String &name);
+	Keymap *getKeymap(const String &id) const;
 
 	/**
 	 * Obtain a list of all the keymaps registered with the keymapper
diff --git a/backends/keymapper/remap-widget.cpp b/backends/keymapper/remap-widget.cpp
index 7a87519..cbf2a54 100644
--- a/backends/keymapper/remap-widget.cpp
+++ b/backends/keymapper/remap-widget.cpp
@@ -284,7 +284,7 @@ void RemapWidget::refreshKeymap() {
 		row.resetButton->setTooltip(_("Reset to defaults"));
 
 		if (!_keymapSeparators.contains(row.keymap)) {
-			_keymapSeparators[row.keymap] = new GUI::StaticTextWidget(_scrollContainer, 0, 0, 0, 0, row.keymap->getName(), Graphics::kTextAlignLeft);
+			_keymapSeparators[row.keymap] = new GUI::StaticTextWidget(_scrollContainer, 0, 0, 0, 0, row.keymap->getDescription(), Graphics::kTextAlignLeft);
 		}
 	}
 }
diff --git a/backends/platform/maemo/maemo.cpp b/backends/platform/maemo/maemo.cpp
index ef44b58..64d059e 100644
--- a/backends/platform/maemo/maemo.cpp
+++ b/backends/platform/maemo/maemo.cpp
@@ -195,7 +195,7 @@ Common::KeymapArray OSystem_SDL_Maemo::getGlobalKeymaps() {
 	using namespace Common;
 	KeymapArray globalMaps = OSystem_POSIX::getGlobalKeymaps();
 
-	Keymap *globalMap = new Keymap(Keymap::kKeymapTypeGlobal, "maemo");
+	Keymap *globalMap = new Keymap(Keymap::kKeymapTypeGlobal, "maemo", "Maemo");
 
 	Action *act;
 
diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
index 7361b0e..4982ac1 100644
--- a/engines/kyra/engine/eobcommon.cpp
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -344,7 +344,7 @@ EoBCoreEngine::~EoBCoreEngine() {
 }
 
 Common::Keymap *EoBCoreEngine::initKeymap(const Common::String &gameId) {
-	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, kKeymapName);
+	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, kKeymapName, "Eye of the Beholder");
 
 	const Common::KeyActionEntry keyActionEntries[] = {
 		{ "MVF", Common::KEYCODE_UP,     "UP",     _("Move Forward")                      },
diff --git a/engines/kyra/engine/lol.cpp b/engines/kyra/engine/lol.cpp
index 4503c0b..b0b5697 100644
--- a/engines/kyra/engine/lol.cpp
+++ b/engines/kyra/engine/lol.cpp
@@ -462,7 +462,7 @@ Common::Error LoLEngine::init() {
 }
 
 Common::Keymap *LoLEngine::initKeymap() {
-	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, kKeymapName);
+	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, kKeymapName, "Lands of Lore");
 
 	const Common::KeyActionEntry keyActionEntries[] = {
 		{ "AT1", Common::KeyState(Common::KEYCODE_F1, Common::ASCII_F1), "F1",     _("Attack 1")     },
diff --git a/engines/metaengine.cpp b/engines/metaengine.cpp
index 8be0ffa..3018f03 100644
--- a/engines/metaengine.cpp
+++ b/engines/metaengine.cpp
@@ -50,7 +50,7 @@ const char *MetaEngine::getSavegamePattern(const char *target) const {
 Common::Keymap *MetaEngine::initKeymap(const char *target) const {
 	using namespace Common;
 
-	Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "engine-default");
+	Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "engine-default", _("Default game keymap"));
 
 	Action *act;
 
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index a64515c..93fc0f4 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -875,7 +875,7 @@ void MohawkEngine_Riven::runOptionsDialog() {
 Common::Keymap *MohawkEngine_Riven::initKeymap(const char *target) {
 	using namespace Common;
 
-	Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "riven");
+	Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "riven", "Riven");
 
 	if (checkGameGUIOption(GAMEOPTION_25TH, ConfMan.get("guioptions", target))) {
 		Action* const act = new Action(kStandardActionOpenMainMenu, _("Open main menu"));
diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp
index 524fec4..92caaff 100644
--- a/engines/pegasus/pegasus.cpp
+++ b/engines/pegasus/pegasus.cpp
@@ -2492,7 +2492,7 @@ uint PegasusEngine::getNeighborhoodCD(const NeighborhoodID neighborhood) const {
 Common::Keymap *PegasusEngine::initKeymap() {
 	using namespace Common;
 
-	Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "pegasus");
+	Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "pegasus", "Pegasus Prime");
 
 	Action *act;
 
diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp
index 9114e17..868a813 100644
--- a/gui/gui-manager.cpp
+++ b/gui/gui-manager.cpp
@@ -113,7 +113,7 @@ GuiManager::~GuiManager() {
 Common::Keymap *GuiManager::getKeymap() const {
 	using namespace Common;
 
-	Keymap *guiMap = new Keymap(Keymap::kKeymapTypeGui, kGuiKeymapName);
+	Keymap *guiMap = new Keymap(Keymap::kKeymapTypeGui, kGuiKeymapName, _("GUI"));
 
 	Action *act;
 


Commit: 519b4a57e242308a1aaaa24b7e70415206fc213a
    https://github.com/scummvm/scummvm/commit/519b4a57e242308a1aaaa24b7e70415206fc213a
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
KEYMAPPER: Allow engines to return multiple keymaps

The idea is that keymaps may be situational. A keymap may be always
enabled, while another one may be enabled only during combat..

Changed paths:
    backends/keymapper/keymap.h
    backends/keymapper/keymapper.h
    base/main.cpp
    engines/kyra/detection.cpp
    engines/kyra/engine/eobcommon.cpp
    engines/kyra/engine/eobcommon.h
    engines/kyra/engine/lol.cpp
    engines/kyra/engine/lol.h
    engines/metaengine.cpp
    engines/metaengine.h
    engines/mohawk/detection.cpp
    engines/mohawk/riven.cpp
    engines/mohawk/riven.h
    engines/pegasus/detection.cpp
    engines/pegasus/pegasus.cpp
    engines/pegasus/pegasus.h
    gui/editgamedialog.cpp
    gui/options.cpp
    gui/options.h


diff --git a/backends/keymapper/keymap.h b/backends/keymapper/keymap.h
index 22dbf14..d81cfd4 100644
--- a/backends/keymapper/keymap.h
+++ b/backends/keymapper/keymap.h
@@ -149,6 +149,11 @@ public:
 	bool isEnabled() const { return _enabled; }
 	void setEnabled(bool enabled) { _enabled = enabled; }
 
+	/** Helper to return an array with a single keymap element */
+	static Array<Keymap *> arrayOf(Keymap *keymap) {
+		return Array<Keymap *>(1, keymap);
+	}
+
 private:
 
 	const Action *findAction(const char *id) const;
@@ -174,6 +179,7 @@ private:
 	void registerBackendDefaultMappings();
 };
 
+typedef Array<Keymap *> KeymapArray;
 
 } // End of namespace Common
 
diff --git a/backends/keymapper/keymapper.h b/backends/keymapper/keymapper.h
index b1e1c76..3c0317e 100644
--- a/backends/keymapper/keymapper.h
+++ b/backends/keymapper/keymapper.h
@@ -42,8 +42,6 @@ struct HardwareInput;
 class HardwareInputSet;
 class KeymapperDefaultBindings;
 
-typedef Array<Keymap *> KeymapArray;
-
 class Keymapper : public Common::EventMapper {
 public:
 
diff --git a/base/main.cpp b/base/main.cpp
index 048640e..d149ed5 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -282,10 +282,10 @@ static Common::Error runGame(const Plugin *plugin, OSystem &system, const Common
 #endif // USE_TRANSLATION
 
 	// Initialize any game-specific keymaps
-	Common::Keymap *gameKeymap = metaEngine.initKeymap(target.c_str());
+	Common::KeymapArray gameKeymaps = metaEngine.initKeymaps(target.c_str());
 	Common::Keymapper *keymapper = system.getEventManager()->getKeymapper();
-	if (gameKeymap) {
-		keymapper->addGameKeymap(gameKeymap);
+	for (uint i = 0; i < gameKeymaps.size(); i++) {
+		keymapper->addGameKeymap(gameKeymaps[i]);
 	}
 
 	// Inform backend that the engine is about to be run
diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp
index d0594b9..91e791d 100644
--- a/engines/kyra/detection.cpp
+++ b/engines/kyra/detection.cpp
@@ -182,7 +182,7 @@ public:
 	virtual int getMaximumSaveSlot() const;
 	void removeSaveState(const char *target, int slot) const;
 	SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
-	Common::Keymap *initKeymap(const char *target) const override;
+	Common::KeymapArray initKeymaps(const char *target) const override;
 };
 
 bool KyraMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -352,22 +352,22 @@ SaveStateDescriptor KyraMetaEngine::querySaveMetaInfos(const char *target, int s
 	return desc;
 }
 
-Common::Keymap *KyraMetaEngine::initKeymap(const char *target) const {
+Common::KeymapArray KyraMetaEngine::initKeymaps(const char *target) const {
 	Common::String gameId = ConfMan.get("gameid", target);
 
 #ifdef ENABLE_LOL
 	if (gameId.contains("lol")) {
-		return Kyra::LoLEngine::initKeymap();
+		return Kyra::LoLEngine::initKeymaps();
 	}
 #endif
 
 #ifdef ENABLE_EOB
 	if (gameId.contains("eob")) {
-		return Kyra::EoBCoreEngine::initKeymap(gameId);
+		return Kyra::EoBCoreEngine::initKeymaps(gameId);
 	}
 #endif
 
-	return AdvancedMetaEngine::initKeymap(target);
+	return AdvancedMetaEngine::initKeymaps(target);
 }
 
 #if PLUGIN_ENABLED_DYNAMIC(KYRA)
diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
index 4982ac1..e812303 100644
--- a/engines/kyra/engine/eobcommon.cpp
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -343,7 +343,7 @@ EoBCoreEngine::~EoBCoreEngine() {
 	_txt = 0;
 }
 
-Common::Keymap *EoBCoreEngine::initKeymap(const Common::String &gameId) {
+Common::KeymapArray EoBCoreEngine::initKeymaps(const Common::String &gameId) {
 	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, kKeymapName, "Eye of the Beholder");
 
 	const Common::KeyActionEntry keyActionEntries[] = {
@@ -380,7 +380,7 @@ Common::Keymap *EoBCoreEngine::initKeymap(const Common::String &gameId) {
 		engineKeyMap->addAction(act);
 	}
 
-	return engineKeyMap;
+	return Common::Keymap::arrayOf(engineKeyMap);
 }
 
 Common::Error EoBCoreEngine::init() {
diff --git a/engines/kyra/engine/eobcommon.h b/engines/kyra/engine/eobcommon.h
index 7b4ff66..4c96c4f 100644
--- a/engines/kyra/engine/eobcommon.h
+++ b/engines/kyra/engine/eobcommon.h
@@ -255,7 +255,7 @@ public:
 	EoBCoreEngine(OSystem *system, const GameFlags &flags);
 	virtual ~EoBCoreEngine();
 
-	static Common::Keymap *initKeymap(const Common::String &ameId);
+	static Common::Array<Common::Keymap *> initKeymaps(const Common::String &ameId);
 
 	Screen *screen() { return _screen; }
 	GUI *gui() const { return _gui; }
diff --git a/engines/kyra/engine/lol.cpp b/engines/kyra/engine/lol.cpp
index b0b5697..cb48a27 100644
--- a/engines/kyra/engine/lol.cpp
+++ b/engines/kyra/engine/lol.cpp
@@ -461,8 +461,8 @@ Common::Error LoLEngine::init() {
 	return Common::kNoError;
 }
 
-Common::Keymap *LoLEngine::initKeymap() {
-	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, kKeymapName, "Lands of Lore");
+Common::KeymapArray LoLEngine::initKeymaps() {
+	Common::Keymap *engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, kKeymapName, "Lands of Lore");
 
 	const Common::KeyActionEntry keyActionEntries[] = {
 		{ "AT1", Common::KeyState(Common::KEYCODE_F1, Common::ASCII_F1), "F1",     _("Attack 1")     },
@@ -487,7 +487,7 @@ Common::Keymap *LoLEngine::initKeymap() {
 		engineKeyMap->addAction(act);
 	}
 
-	return engineKeyMap;
+	return Common::Keymap::arrayOf(engineKeyMap);
 }
 
 void LoLEngine::pauseEngineIntern(bool pause) {
diff --git a/engines/kyra/engine/lol.h b/engines/kyra/engine/lol.h
index 11d897b..a1493b1 100644
--- a/engines/kyra/engine/lol.h
+++ b/engines/kyra/engine/lol.h
@@ -272,7 +272,7 @@ public:
 	LoLEngine(OSystem *system, const GameFlags &flags);
 	virtual ~LoLEngine();
 
-	static Common::Keymap *initKeymap();
+	static Common::Array<Common::Keymap *> initKeymaps();
 
 	void pauseEngineIntern(bool pause);
 
diff --git a/engines/metaengine.cpp b/engines/metaengine.cpp
index 3018f03..6b88c42 100644
--- a/engines/metaengine.cpp
+++ b/engines/metaengine.cpp
@@ -47,7 +47,7 @@ const char *MetaEngine::getSavegamePattern(const char *target) const {
 	return buffer;
 }
 
-Common::Keymap *MetaEngine::initKeymap(const char *target) const {
+Common::KeymapArray MetaEngine::initKeymaps(const char *target) const {
 	using namespace Common;
 
 	Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "engine-default", _("Default game keymap"));
@@ -118,7 +118,7 @@ Common::Keymap *MetaEngine::initKeymap(const char *target) const {
 	act->addDefaultInputMapping("JOY_RIGHT");
 	engineKeyMap->addAction(act);
 
-	return engineKeyMap;
+	return Keymap::arrayOf(engineKeyMap);
 }
 
 void MetaEngine::appendExtendedSave(Common::OutSaveFile *saveFile, uint32 playtime, Common::String desc) {
diff --git a/engines/metaengine.h b/engines/metaengine.h
index 10e5fbf..7117ad2 100644
--- a/engines/metaengine.h
+++ b/engines/metaengine.h
@@ -220,7 +220,7 @@ public:
 	/**
 	 * Return the keymap used by the target.
 	 */
-	virtual Common::Keymap *initKeymap(const char *target) const;
+	virtual Common::Array<Common::Keymap *> initKeymaps(const char *target) const;
 
 	/** @name MetaEngineFeature flags */
 	//@{
diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp
index c3c4e11..c5bf935 100644
--- a/engines/mohawk/detection.cpp
+++ b/engines/mohawk/detection.cpp
@@ -226,7 +226,7 @@ public:
 	int getMaximumSaveSlot() const override { return 999; }
 	void removeSaveState(const char *target, int slot) const override;
 	SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const override;
-	Common::Keymap *initKeymap(const char *target) const override;
+	Common::KeymapArray initKeymaps(const char *target) const override;
 };
 
 bool MohawkMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -331,16 +331,16 @@ SaveStateDescriptor MohawkMetaEngine::querySaveMetaInfos(const char *target, int
 	}
 }
 
-Common::Keymap *MohawkMetaEngine::initKeymap(const char *target) const {
+Common::KeymapArray MohawkMetaEngine::initKeymaps(const char *target) const {
 	Common::String gameId = ConfMan.get("gameid", target);
 
 #ifdef ENABLE_RIVEN
 	if (gameId == "riven") {
-		return Mohawk::MohawkEngine_Riven::initKeymap(target);
+		return Mohawk::MohawkEngine_Riven::initKeymaps(target);
 	}
 #endif
 
-	return AdvancedMetaEngine::initKeymap(target);
+	return AdvancedMetaEngine::initKeymaps(target);
 }
 
 bool MohawkMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index 93fc0f4..eef2796 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -872,7 +872,7 @@ void MohawkEngine_Riven::runOptionsDialog() {
 	_card->initializeZipMode();
 }
 
-Common::Keymap *MohawkEngine_Riven::initKeymap(const char *target) {
+Common::KeymapArray MohawkEngine_Riven::initKeymaps(const char *target) {
 	using namespace Common;
 
 	Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "riven", "Riven");
@@ -930,7 +930,7 @@ Common::Keymap *MohawkEngine_Riven::initKeymap(const char *target) {
 		}
 	}
 
-	return engineKeyMap;
+	return Keymap::arrayOf(engineKeyMap);
 }
 
 bool ZipMode::operator== (const ZipMode &z) const {
diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h
index b5acc8b..ab55dd2 100644
--- a/engines/mohawk/riven.h
+++ b/engines/mohawk/riven.h
@@ -108,7 +108,7 @@ public:
 	Common::Error loadGameState(int slot) override;
 	Common::Error saveGameState(int slot, const Common::String &desc) override;
 	bool hasFeature(EngineFeature f) const override;
-	static Common::Keymap *initKeymap(const char *target);
+	static Common::Array<Common::Keymap *> initKeymaps(const char *target);
 
 	void doFrame();
 	void processInput();
diff --git a/engines/pegasus/detection.cpp b/engines/pegasus/detection.cpp
index 5d723d4..3263781 100644
--- a/engines/pegasus/detection.cpp
+++ b/engines/pegasus/detection.cpp
@@ -153,7 +153,7 @@ public:
 	virtual SaveStateList listSaves(const char *target) const;
 	virtual int getMaximumSaveSlot() const { return 999; }
 	virtual void removeSaveState(const char *target, int slot) const;
-	Common::Keymap *initKeymap(const char *target) const override;
+	Common::KeymapArray initKeymaps(const char *target) const override;
 };
 
 bool PegasusMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -188,8 +188,8 @@ void PegasusMetaEngine::removeSaveState(const char *target, int slot) const {
 	g_system->getSavefileManager()->removeSavefile(fileNames[slot].c_str());
 }
 
-Common::Keymap *PegasusMetaEngine::initKeymap(const char *target) const {
-	return Pegasus::PegasusEngine::initKeymap();
+Common::KeymapArray PegasusMetaEngine::initKeymaps(const char *target) const {
+	return Pegasus::PegasusEngine::initKeymaps();
 }
 
 bool PegasusMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp
index 92caaff..0b16e01 100644
--- a/engines/pegasus/pegasus.cpp
+++ b/engines/pegasus/pegasus.cpp
@@ -2489,7 +2489,7 @@ uint PegasusEngine::getNeighborhoodCD(const NeighborhoodID neighborhood) const {
 	return 1;
 }
 
-Common::Keymap *PegasusEngine::initKeymap() {
+Common::KeymapArray PegasusEngine::initKeymaps() {
 	using namespace Common;
 
 	Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "pegasus", "Pegasus Prime");
@@ -2609,7 +2609,7 @@ Common::Keymap *PegasusEngine::initKeymap() {
 	act->addDefaultInputMapping("M+l");
 	engineKeyMap->addAction(act);
 
-	return engineKeyMap;
+	return Keymap::arrayOf(engineKeyMap);
 }
 
 } // End of namespace Pegasus
diff --git a/engines/pegasus/pegasus.h b/engines/pegasus/pegasus.h
index 65af8c6..3e41181 100644
--- a/engines/pegasus/pegasus.h
+++ b/engines/pegasus/pegasus.h
@@ -83,7 +83,7 @@ public:
 	bool canSaveGameStateCurrently();
 	Common::Error loadGameState(int slot);
 	Common::Error saveGameState(int slot, const Common::String &desc);
-	static Common::Keymap *initKeymap();
+	static Common::Array<Common::Keymap *> initKeymaps();
 
 	// Base classes
 	GraphicsManager *_gfx;
diff --git a/gui/editgamedialog.cpp b/gui/editgamedialog.cpp
index cdabb4e..76a5e53 100644
--- a/gui/editgamedialog.cpp
+++ b/gui/editgamedialog.cpp
@@ -200,21 +200,14 @@ EditGameDialog::EditGameDialog(const String &domain)
 	//
 	// The Keymap tab
 	//
-	Common::Keymap *keymap = nullptr;
+	Common::KeymapArray keymaps;
 	if (plugin) {
-		keymap = plugin->get<MetaEngine>().initKeymap(domain.c_str());
+		keymaps = plugin->get<MetaEngine>().initKeymaps(domain.c_str());
 	}
 
-	if (keymap && !keymap->getActions().empty()) {
-		Common::Keymapper *keymapper = g_system->getEventManager()->getKeymapper();
-
-		keymapper->initKeymap(keymap, ConfMan.getDomain(domain));
-
-		Common::KeymapArray keymaps;
-		keymaps.push_back(keymap);
-
+	if (!keymaps.empty()) {
 		tab->addTab(_("Keymaps"), "GameOptions_KeyMapper");
-		addKeyMapperControls(tab, "GameOptions_KeyMapper.", keymaps);
+		addKeyMapperControls(tab, "GameOptions_KeyMapper.", keymaps, domain);
 	}
 
 	//
diff --git a/gui/options.cpp b/gui/options.cpp
index be4ef97..8573147 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -1057,7 +1057,12 @@ void OptionsDialog::addControlControls(GuiObject *boss, const Common::String &pr
 	_enableControlSettings = true;
 }
 
-void OptionsDialog::addKeyMapperControls(GuiObject *boss, const Common::String &prefix, const Common::KeymapArray &keymaps) {
+void OptionsDialog::addKeyMapperControls(GuiObject *boss, const Common::String &prefix, const Common::KeymapArray &keymaps, const Common::String &domain) {
+	Common::Keymapper *mapper = g_system->getEventManager()->getKeymapper();
+	for (uint i = 0; i < keymaps.size(); i++) {
+		mapper->initKeymap(keymaps[i], ConfMan.getDomain(domain));
+	}
+
 	_keymapperWidget = new Common::RemapWidget(boss, prefix + "Container", keymaps);
 }
 
@@ -1623,16 +1628,9 @@ void GlobalOptionsDialog::build() {
 		keymaps.push_back(guiKeymap);
 	}
 
-	Common::Keymapper *mapper = g_system->getEventManager()->getKeymapper();
-	Common::ConfigManager::Domain *keymapperDomain = ConfMan.getDomain(Common::ConfigManager::kKeymapperDomain);
-
-	for (uint i = 0; i < keymaps.size(); i++) {
-		mapper->initKeymap(keymaps[i], keymapperDomain);
-	}
-
 	if (!keymaps.empty()) {
 		tab->addTab(_("Keymaps"), "GlobalOptions_KeyMapper");
-		addKeyMapperControls(tab, "GlobalOptions_KeyMapper.", keymaps);
+		addKeyMapperControls(tab, "GlobalOptions_KeyMapper.", keymaps, Common::ConfigManager::kKeymapperDomain);
 	}
 
 	//
diff --git a/gui/options.h b/gui/options.h
index 075f8ff..dd34ac9 100644
--- a/gui/options.h
+++ b/gui/options.h
@@ -94,7 +94,7 @@ protected:
 
 
 	void addControlControls(GuiObject *boss, const Common::String &prefix);
-	void addKeyMapperControls(GuiObject *boss, const Common::String &prefix, const Common::Array<Common::Keymap *> &keymaps);
+	void addKeyMapperControls(GuiObject *boss, const Common::String &prefix, const Common::Array<Common::Keymap *> &keymaps, const Common::String &domain);
 	void addGraphicControls(GuiObject *boss, const Common::String &prefix);
 	void addShaderControls(GuiObject *boss, const Common::String &prefix);
 	void addAudioControls(GuiObject *boss, const Common::String &prefix);


Commit: e973092aef7dfd513f0b3ea9f928eab9855a0fc9
    https://github.com/scummvm/scummvm/commit/e973092aef7dfd513f0b3ea9f928eab9855a0fc9
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
KEYMAPPER: Enable remapping of the mouse buttons

Changed paths:
    backends/keymapper/hardware-input.cpp
    backends/keymapper/hardware-input.h
    backends/keymapper/input-watcher.cpp
    backends/keymapper/keymap.cpp
    backends/keymapper/keymapper.cpp
    backends/platform/maemo/maemo.cpp
    backends/platform/sdl/sdl.cpp
    common/events.h
    engines/metaengine.cpp


diff --git a/backends/keymapper/hardware-input.cpp b/backends/keymapper/hardware-input.cpp
index 195910b..ce14c5f 100644
--- a/backends/keymapper/hardware-input.cpp
+++ b/backends/keymapper/hardware-input.cpp
@@ -217,6 +217,13 @@ const ModifierTableEntry defaultModifiers[] = {
 	{ 0,     nullptr, nullptr }
 };
 
+const HardwareInputTableEntry defaultMouseButtons[] = {
+    { "MOUSE_LEFT",   MOUSE_BUTTON_LEFT,   _s("Left Mouse Button")   },
+    { "MOUSE_RIGHT",  MOUSE_BUTTON_RIGHT,  _s("Right Mouse Button")  },
+    { "MOUSE_MIDDLE", MOUSE_BUTTON_MIDDLE, _s("Middle Mouse Button") },
+    { nullptr,        0,                   nullptr                   }
+};
+
 const HardwareInputTableEntry defaultJoystickButtons[] = {
     { "JOY_A",              JOYSTICK_BUTTON_A,              _s("Joy A")              },
     { "JOY_B",              JOYSTICK_BUTTON_B,              _s("Joy B")              },
@@ -329,18 +336,59 @@ HardwareInput KeyboardHardwareInputSet::findHardwareInput(const Event &event) co
 	}
 }
 
-JoystickHardwareInputSet::JoystickHardwareInputSet(const HardwareInputTableEntry *buttonEntries) :
-    _buttonEntries(buttonEntries) {
+MouseHardwareInputSet::MouseHardwareInputSet(const HardwareInputTableEntry *buttonEntries) :
+		_buttonEntries(buttonEntries) {
+	assert(_buttonEntries);
 }
 
-HardwareInput JoystickHardwareInputSet::findHardwareInput(const String &id) const {
-	const HardwareInputTableEntry *hw = nullptr;
-	for (hw = _buttonEntries;  hw->hwId; hw++) {
-		if (id.equals(hw->hwId)) {
-			break;
-		}
+HardwareInput MouseHardwareInputSet::findHardwareInput(const String &id) const {
+	const HardwareInputTableEntry *hw = HardwareInputTableEntry::findWithId(_buttonEntries, id);
+	if (!hw || !hw->hwId) {
+		return HardwareInput();
+	}
+
+	return HardwareInput::createMouse(hw->hwId, hw->code, hw->desc);
+}
+
+HardwareInput MouseHardwareInputSet::findHardwareInput(const Event &event) const {
+	int button;
+	switch (event.type) {
+	case EVENT_LBUTTONDOWN:
+	case EVENT_LBUTTONUP:
+		button = MOUSE_BUTTON_LEFT;
+		break;
+	case EVENT_RBUTTONDOWN:
+	case EVENT_RBUTTONUP:
+		button = MOUSE_BUTTON_RIGHT;
+		break;
+	case EVENT_MBUTTONDOWN:
+	case EVENT_MBUTTONUP:
+		button = MOUSE_BUTTON_MIDDLE;
+		break;
+	default:
+		button = -1;
+		break;
+	}
+
+	if (button == -1) {
+		return HardwareInput();
 	}
 
+	const HardwareInputTableEntry *hw = HardwareInputTableEntry::findWithCode(_buttonEntries, button);
+	if (!hw || !hw->hwId) {
+		return HardwareInput();
+	}
+
+	return HardwareInput::createMouse(hw->hwId, hw->code, hw->desc);
+}
+
+JoystickHardwareInputSet::JoystickHardwareInputSet(const HardwareInputTableEntry *buttonEntries) :
+		_buttonEntries(buttonEntries) {
+	assert(_buttonEntries);
+}
+
+HardwareInput JoystickHardwareInputSet::findHardwareInput(const String &id) const {
+	const HardwareInputTableEntry *hw = HardwareInputTableEntry::findWithId(_buttonEntries, id);
 	if (!hw || !hw->hwId) {
 		return HardwareInput();
 	}
@@ -352,13 +400,7 @@ HardwareInput JoystickHardwareInputSet::findHardwareInput(const Event &event) co
 	switch (event.type) {
 	case EVENT_JOYBUTTON_DOWN:
 	case EVENT_JOYBUTTON_UP: {
-		const HardwareInputTableEntry *hw = nullptr;
-		for (hw = _buttonEntries;  hw->hwId; hw++) {
-			if (event.joystick.button == hw->code) {
-				break;
-			}
-		}
-
+		const HardwareInputTableEntry *hw = HardwareInputTableEntry::findWithCode(_buttonEntries, event.joystick.button);
 		if (!hw || !hw->hwId) {
 			return HardwareInput();
 		}
@@ -376,13 +418,7 @@ CustomHardwareInputSet::CustomHardwareInputSet(const HardwareInputTableEntry *ha
 }
 
 HardwareInput CustomHardwareInputSet::findHardwareInput(const String &id) const {
-	const HardwareInputTableEntry *hw = nullptr;
-	for (hw = _hardwareEntries;  hw->hwId; hw++) {
-		if (id.equals(hw->hwId)) {
-			break;
-		}
-	}
-
+	const HardwareInputTableEntry *hw = HardwareInputTableEntry::findWithId(_hardwareEntries, id);
 	if (!hw || !hw->hwId) {
 		return HardwareInput();
 	}
@@ -393,13 +429,7 @@ HardwareInput CustomHardwareInputSet::findHardwareInput(const String &id) const
 HardwareInput CustomHardwareInputSet::findHardwareInput(const Event &event) const {
 	switch (event.type) {
 	case EVENT_CUSTOM_BACKEND_HARDWARE: {
-		const HardwareInputTableEntry *hw = nullptr;
-		for (hw = _hardwareEntries;  hw->hwId; hw++) {
-			if (event.customType == hw->code) {
-				break;
-			}
-		}
-
+		const HardwareInputTableEntry *hw = HardwareInputTableEntry::findWithCode(_hardwareEntries, event.customType);
 		if (!hw || !hw->hwId) {
 			return HardwareInput();
 		}
diff --git a/backends/keymapper/hardware-input.h b/backends/keymapper/hardware-input.h
index d6e3f7d..bde98f6 100644
--- a/backends/keymapper/hardware-input.h
+++ b/backends/keymapper/hardware-input.h
@@ -37,12 +37,14 @@ typedef uint32 HardwareInputCode;
 enum HardwareInputType {
 	/** Empty / invalid input type */
 	kHardwareInputTypeInvalid,
-	/** Input that sends single events */
-	kHardwareInputTypeCustom,
 	/** Keyboard input that sends -up and -down events */
 	kHardwareInputTypeKeyboard,
+	/** Mouse input that sends -up and -down events */
+	kHardwareInputTypeMouse,
 	/** Joystick input that sends -up and -down events */
-	kHardwareInputTypeJoystick
+	kHardwareInputTypeJoystick,
+	/** Input that sends single events */
+	kHardwareInputTypeCustom
 };
 
 /**
@@ -76,12 +78,7 @@ struct HardwareInput {
 		: inputCode(0), type(kHardwareInputTypeInvalid) { }
 
 	static HardwareInput createCustom(const String &i, HardwareInputCode ic, const String &desc) {
-		HardwareInput hardwareInput;
-		hardwareInput.id = i;
-		hardwareInput.description = desc;
-		hardwareInput.type = kHardwareInputTypeCustom;
-		hardwareInput.inputCode = ic;
-		return hardwareInput;
+		return createSimple(kHardwareInputTypeCustom, i, ic, desc);
 	}
 
 	static HardwareInput createKeyboard(const String &i, KeyState ky, const String &desc) {
@@ -95,11 +92,21 @@ struct HardwareInput {
 	}
 
 	static HardwareInput createJoystick(const String &i, uint8 button, const String &desc) {
+		return createSimple(kHardwareInputTypeJoystick, i, button, desc);
+	}
+
+	static HardwareInput createMouse(const String &i, uint8 button, const String &desc) {
+		return createSimple(kHardwareInputTypeMouse, i, button, desc);
+
+	}
+
+private:
+	static HardwareInput createSimple(HardwareInputType type, const String &i, HardwareInputCode ic, const String &desc) {
 		HardwareInput hardwareInput;
 		hardwareInput.id = i;
 		hardwareInput.description = desc;
-		hardwareInput.type = kHardwareInputTypeJoystick;
-		hardwareInput.inputCode = button;
+		hardwareInput.type = type;
+		hardwareInput.inputCode = ic;
 		return hardwareInput;
 	}
 };
@@ -111,6 +118,24 @@ struct HardwareInputTableEntry {
 	const char *hwId;
 	HardwareInputCode code;
 	const char *desc;
+
+	static const HardwareInputTableEntry *findWithCode(const HardwareInputTableEntry *_entries, HardwareInputCode code) {
+		for (const HardwareInputTableEntry *hw = _entries;  hw->hwId; hw++) {
+			if (hw->code == code) {
+				return hw;
+			}
+		}
+		return nullptr;
+	}
+
+	static const HardwareInputTableEntry *findWithId(const HardwareInputTableEntry *_entries, const String &id) {
+		for (const HardwareInputTableEntry *hw = _entries;  hw->hwId; hw++) {
+			if (id.equals(hw->hwId)) {
+				return hw;
+			}
+		}
+		return nullptr;
+	}
 };
 
 /**
@@ -177,6 +202,23 @@ private:
 };
 
 /**
+ * A mouse input device
+ *
+ * Describes the mouse buttons
+ */
+class MouseHardwareInputSet : public HardwareInputSet {
+public:
+	MouseHardwareInputSet(const HardwareInputTableEntry *buttonEntries);
+
+	// HardwareInputSet API
+	HardwareInput findHardwareInput(const String &id) const override;
+	HardwareInput findHardwareInput(const Event &event) const override;
+
+private:
+	const HardwareInputTableEntry *_buttonEntries;
+};
+
+/**
  * A joystick input device
  */
 class JoystickHardwareInputSet : public HardwareInputSet {
@@ -236,6 +278,9 @@ extern const KeyTableEntry defaultKeys[];
 /** A standard set of keyboard modifiers */
 extern const ModifierTableEntry defaultModifiers[];
 
+/** A standard set of mouse buttons */
+extern const HardwareInputTableEntry defaultMouseButtons[];
+
 /** A standard set of joystick buttons based on the ScummVM event model */
 extern const HardwareInputTableEntry defaultJoystickButtons[];
 
diff --git a/backends/keymapper/input-watcher.cpp b/backends/keymapper/input-watcher.cpp
index 236cfdc..685d6b6 100644
--- a/backends/keymapper/input-watcher.cpp
+++ b/backends/keymapper/input-watcher.cpp
@@ -60,9 +60,15 @@ bool InputWatcher::notifyEvent(const Event &event) {
 	switch (event.type) {
 		case EVENT_KEYDOWN:
 		case EVENT_JOYBUTTON_DOWN:
+		case EVENT_LBUTTONDOWN:
+		case EVENT_RBUTTONDOWN:
+		case EVENT_MBUTTONDOWN:
 			return true;
 		case EVENT_KEYUP:
 		case EVENT_JOYBUTTON_UP:
+		case EVENT_LBUTTONUP:
+		case EVENT_RBUTTONUP:
+		case EVENT_MBUTTONUP:
 		case EVENT_CUSTOM_BACKEND_HARDWARE:
 			_hwInput = _keymapper->findHardwareInput(event);
 			if (_hwInput.type != kHardwareInputTypeInvalid) {
diff --git a/backends/keymapper/keymap.cpp b/backends/keymapper/keymap.cpp
index 51f6207..84b939b 100644
--- a/backends/keymapper/keymap.cpp
+++ b/backends/keymapper/keymap.cpp
@@ -119,6 +119,21 @@ Keymap::ActionArray Keymap::getMappedActions(const Event &event) const {
 		HardwareInput hardwareInput = HardwareInput::createKeyboard("", event.kbd, "");
 		return _hwActionMap[hardwareInput];
 	}
+	case EVENT_LBUTTONDOWN:
+	case EVENT_LBUTTONUP: {
+		HardwareInput hardwareInput = HardwareInput::createMouse("", MOUSE_BUTTON_LEFT, "");
+		return _hwActionMap[hardwareInput];
+	}
+	case EVENT_RBUTTONDOWN:
+	case EVENT_RBUTTONUP: {
+		HardwareInput hardwareInput = HardwareInput::createMouse("", MOUSE_BUTTON_RIGHT, "");
+		return _hwActionMap[hardwareInput];
+	}
+	case EVENT_MBUTTONDOWN:
+	case EVENT_MBUTTONUP: {
+		HardwareInput hardwareInput = HardwareInput::createMouse("", MOUSE_BUTTON_MIDDLE, "");
+		return _hwActionMap[hardwareInput];
+	}
 	case EVENT_JOYBUTTON_DOWN:
 	case EVENT_JOYBUTTON_UP: {
 		HardwareInput hardwareInput = HardwareInput::createJoystick("", event.joystick.button, "");
diff --git a/backends/keymapper/keymapper.cpp b/backends/keymapper/keymapper.cpp
index acd1e64..649db85 100644
--- a/backends/keymapper/keymapper.cpp
+++ b/backends/keymapper/keymapper.cpp
@@ -56,7 +56,10 @@ void Keymapper::registerHardwareInputSet(HardwareInputSet *inputs) {
 
 	if (!inputs) {
 		warning("No hardware input were defined, using defaults");
-		inputs = new KeyboardHardwareInputSet(defaultKeys, defaultModifiers);
+		CompositeHardwareInputSet *compositeInputs = new CompositeHardwareInputSet();
+		compositeInputs->addHardwareInputSet(new MouseHardwareInputSet(defaultMouseButtons));
+		compositeInputs->addHardwareInputSet(new KeyboardHardwareInputSet(defaultKeys, defaultModifiers));
+		inputs = compositeInputs;
 	}
 
 	_hardwareInputs = inputs;
@@ -191,7 +194,11 @@ List<Event> Keymapper::mapEvent(const Event &ev) {
 Keymapper::IncomingEventType Keymapper::convertToIncomingEventType(const Event &ev) const {
 	if (ev.type == EVENT_CUSTOM_BACKEND_HARDWARE) {
 		return kIncomingEventInstant;
-	} else if (ev.type == EVENT_KEYDOWN || ev.type == EVENT_JOYBUTTON_DOWN) {
+	} else if (ev.type == EVENT_KEYDOWN
+	           || ev.type == EVENT_LBUTTONDOWN
+	           || ev.type == EVENT_RBUTTONDOWN
+	           || ev.type == EVENT_MBUTTONDOWN
+	           || ev.type == EVENT_JOYBUTTON_DOWN) {
 		return kIncomingEventStart;
 	} else {
 		return kIncomingEventEnd;
diff --git a/backends/platform/maemo/maemo.cpp b/backends/platform/maemo/maemo.cpp
index 64d059e..4b1ee9e 100644
--- a/backends/platform/maemo/maemo.cpp
+++ b/backends/platform/maemo/maemo.cpp
@@ -185,6 +185,7 @@ static const Common::KeyTableEntry maemoKeys[] = {
 
 Common::HardwareInputSet *OSystem_SDL_Maemo::getHardwareInputSet() {
 	Common::CompositeHardwareInputSet *inputSet = new Common::CompositeHardwareInputSet();
+	inputSet->addHardwareInputSet(new Common::MouseHardwareInputSet(Common::defaultMouseButtons));
 	inputSet->addHardwareInputSet(new Common::KeyboardHardwareInputSet(maemoKeys, Common::defaultModifiers));
 	inputSet->addHardwareInputSet(new Common::KeyboardHardwareInputSet(Common::defaultKeys, Common::defaultModifiers));
 
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 309d977..8af126f 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -403,6 +403,7 @@ Common::HardwareInputSet *OSystem_SDL::getHardwareInputSet() {
 	using namespace Common;
 
 	CompositeHardwareInputSet *inputSet = new CompositeHardwareInputSet();
+	inputSet->addHardwareInputSet(new MouseHardwareInputSet(defaultMouseButtons));
 	inputSet->addHardwareInputSet(new KeyboardHardwareInputSet(defaultKeys, defaultModifiers));
 
 	bool joystickSupportEnabled = ConfMan.getInt("joystick_num") >= 0;
diff --git a/common/events.h b/common/events.h
index fdf4f01..11bfc79 100644
--- a/common/events.h
+++ b/common/events.h
@@ -137,6 +137,15 @@ enum JoystickButton {
 	JOYSTICK_BUTTON_DPAD_RIGHT
 };
 
+/**
+ *  The list named buttons available from a mouse
+ */
+enum MouseButton {
+	MOUSE_BUTTON_LEFT   = 0,
+	MOUSE_BUTTON_RIGHT  = 1,
+	MOUSE_BUTTON_MIDDLE = 2
+};
+
 typedef uint32 CustomEventType;
 
 /**
@@ -407,8 +416,8 @@ public:
 	virtual ~EventManager() {}
 
 	enum {
-		LBUTTON = 1 << 0,
-		RBUTTON = 1 << 1
+		LBUTTON = 1 << MOUSE_BUTTON_LEFT,
+		RBUTTON = 1 << MOUSE_BUTTON_RIGHT
 	};
 
 
diff --git a/engines/metaengine.cpp b/engines/metaengine.cpp
index 6b88c42..94d6fe0 100644
--- a/engines/metaengine.cpp
+++ b/engines/metaengine.cpp
@@ -56,15 +56,18 @@ Common::KeymapArray MetaEngine::initKeymaps(const char *target) const {
 
 	act = new Action("LCLK", _("Left Click"));
 	act->setLeftClickEvent();
+	act->addDefaultInputMapping("MOUSE_LEFT");
 	act->addDefaultInputMapping("JOY_A");
 	engineKeyMap->addAction(act);
 
 	act = new Action("MCLK", _("Middle Click"));
+	act->addDefaultInputMapping("MOUSE_MIDDLE");
 	act->setMiddleClickEvent();
 	engineKeyMap->addAction(act);
 
 	act = new Action("RCLK", _("Right Click"));
 	act->setRightClickEvent();
+	act->addDefaultInputMapping("MOUSE_RIGHT");
 	act->addDefaultInputMapping("JOY_B");
 	engineKeyMap->addAction(act);
 


Commit: 7ecccd3b30bc6e0e5705b0e0f567bb6990ab8ece
    https://github.com/scummvm/scummvm/commit/7ecccd3b30bc6e0e5705b0e0f567bb6990ab8ece
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
MOHAWK: RIVEN: Add default joystick action mappings

Changed paths:
    backends/events/default/default-events.cpp
    backends/keymapper/standard-actions.cpp
    backends/keymapper/standard-actions.h
    engines/metaengine.cpp
    engines/mohawk/riven.cpp
    engines/pegasus/pegasus.cpp


diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp
index f9fcafa..c0ceedb 100644
--- a/backends/events/default/default-events.cpp
+++ b/backends/events/default/default-events.cpp
@@ -307,7 +307,7 @@ Common::Keymap *DefaultEventManager::getGlobalKeymap() {
 	Keymap *globalKeymap = new Keymap(Keymap::kKeymapTypeGlobal, kGlobalKeymapName, _("Global"));
 
 	Action *act;
-	act = new Action("MENU", _("Menu"));
+	act = new Action("MENU", _("Global Main Menu"));
 	act->addDefaultInputMapping("C+F5");
 	act->addDefaultInputMapping("JOY_START");
 	act->setEvent(EVENT_MAINMENU);
diff --git a/backends/keymapper/standard-actions.cpp b/backends/keymapper/standard-actions.cpp
index 21b0d62..31a1d99 100644
--- a/backends/keymapper/standard-actions.cpp
+++ b/backends/keymapper/standard-actions.cpp
@@ -27,13 +27,14 @@ namespace Common {
 const char *kStandardActionInteract      = "INTRCT";
 const char *kStandardActionSkip          = "SKIP";
 const char *kStandardActionPause         = "PAUSE";
-const char *kStandardActionMoveForward   = "FWD";
-const char *kStandardActionMoveBackwards = "BWD";
-const char *kStandardActionTurnLeft      = "TL";
-const char *kStandardActionTurnRight     = "TR";
-const char *kStandardActionMoveUpwards   = "UP";
-const char *kStandardActionMoveDownwards = "DOWN";
-const char *kStandardActionOpenDebugger  = "DBG";
+const char *kStandardActionMoveUp        = "UP";
+const char *kStandardActionMoveDown      = "DOWN";
+const char *kStandardActionMoveLeft      = "LEFT";
+const char *kStandardActionMoveRight     = "RIGHT";
 const char *kStandardActionOpenMainMenu  = "MENU";
+const char *kStandardActionLoad          = "LOAD";
+const char *kStandardActionSave          = "SAVE";
+const char *kStandardActionOpenSettings  = "OPTS";
+const char *kStandardActionOpenDebugger  = "DBG";
 
 } //namespace Common
diff --git a/backends/keymapper/standard-actions.h b/backends/keymapper/standard-actions.h
index bcf78a6..7f46361 100644
--- a/backends/keymapper/standard-actions.h
+++ b/backends/keymapper/standard-actions.h
@@ -39,14 +39,15 @@ namespace Common {
 extern const char *kStandardActionInteract;
 extern const char *kStandardActionSkip;
 extern const char *kStandardActionPause;
-extern const char *kStandardActionMoveForward;
-extern const char *kStandardActionMoveBackwards;
-extern const char *kStandardActionTurnLeft;
-extern const char *kStandardActionTurnRight;
-extern const char *kStandardActionMoveUpwards;
-extern const char *kStandardActionMoveDownwards;
-extern const char *kStandardActionOpenDebugger;
+extern const char *kStandardActionMoveUp;
+extern const char *kStandardActionMoveDown;
+extern const char *kStandardActionMoveLeft;
+extern const char *kStandardActionMoveRight;
 extern const char *kStandardActionOpenMainMenu;
+extern const char *kStandardActionLoad;
+extern const char *kStandardActionSave;
+extern const char *kStandardActionOpenSettings;
+extern const char *kStandardActionOpenDebugger;
 
 } //namespace Common
 
diff --git a/engines/metaengine.cpp b/engines/metaengine.cpp
index 94d6fe0..559143b 100644
--- a/engines/metaengine.cpp
+++ b/engines/metaengine.cpp
@@ -24,6 +24,7 @@
 
 #include "backends/keymapper/action.h"
 #include "backends/keymapper/keymap.h"
+#include "backends/keymapper/standard-actions.h"
 
 #include "common/savefile.h"
 #include "common/system.h"
@@ -71,20 +72,21 @@ Common::KeymapArray MetaEngine::initKeymaps(const char *target) const {
 	act->addDefaultInputMapping("JOY_B");
 	engineKeyMap->addAction(act);
 
-	act = new Action("PAUS", _("Pause"));
+	act = new Action(kStandardActionPause, _("Pause"));
 	act->setKeyEvent(KeyState(KEYCODE_SPACE, ' '));
 	act->addDefaultInputMapping("SPACE");
 	engineKeyMap->addAction(act);
 
-	act = new Action("MNU", _("Game menu"));
+	act = new Action(kStandardActionOpenMainMenu, _("Game menu"));
 	act->setKeyEvent(KeyState(KEYCODE_F5, ASCII_F5));
 	act->addDefaultInputMapping("F5");
 	act->addDefaultInputMapping("JOY_LEFT_SHOULDER");
 	engineKeyMap->addAction(act);
 
-	act = new Action("SKCT", _("Skip"));
+	act = new Action(kStandardActionSkip, _("Skip"));
 	act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE));
 	act->addDefaultInputMapping("ESCAPE");
+	act->addDefaultInputMapping("JOY_Y");
 	engineKeyMap->addAction(act);
 
 	act = new Action("SKLI", _("Skip line"));
@@ -101,22 +103,22 @@ Common::KeymapArray MetaEngine::initKeymaps(const char *target) const {
 	act->addDefaultInputMapping("RETURN");
 	engineKeyMap->addAction(act);
 
-	act = new Action("UP", _("Up"));
+	act = new Action(kStandardActionMoveUp, _("Up"));
 	act->setKeyEvent(KEYCODE_KP8);
 	act->addDefaultInputMapping("JOY_UP");
 	engineKeyMap->addAction(act);
 
-	act = new Action("DOWN", _("Down"));
+	act = new Action(kStandardActionMoveDown, _("Down"));
 	act->setKeyEvent(KEYCODE_KP2);
 	act->addDefaultInputMapping("JOY_DOWN");
 	engineKeyMap->addAction(act);
 
-	act = new Action("LEFT", _("Left"));
+	act = new Action(kStandardActionMoveLeft, _("Left"));
 	act->setKeyEvent(KEYCODE_KP4);
 	act->addDefaultInputMapping("JOY_LEFT");
 	engineKeyMap->addAction(act);
 
-	act = new Action("RIGHT", _("Right"));
+	act = new Action(kStandardActionMoveRight, _("Right"));
 	act->setKeyEvent(KEYCODE_KP6);
 	act->addDefaultInputMapping("JOY_RIGHT");
 	engineKeyMap->addAction(act);
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index eef2796..a8883ff 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -257,13 +257,6 @@ void MohawkEngine_Riven::processInput() {
 		case Common::EVENT_MOUSEMOVE:
 			_stack->onMouseMove(event.mouse);
 			break;
-		case Common::EVENT_LBUTTONDOWN:
-			_stack->onMouseDown(_eventMan->getMousePos());
-			break;
-		case Common::EVENT_LBUTTONUP:
-			_stack->onMouseUp(_eventMan->getMousePos());
-			_inventory->checkClick(_eventMan->getMousePos());
-			break;
 		case Common::EVENT_CUSTOM_ENGINE_ACTION_END:
 			switch ((RivenAction)event.customType) {
 			case kRivenActionInteract:
@@ -877,57 +870,105 @@ Common::KeymapArray MohawkEngine_Riven::initKeymaps(const char *target) {
 
 	Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "riven", "Riven");
 
+	Action *act;
+
 	if (checkGameGUIOption(GAMEOPTION_25TH, ConfMan.get("guioptions", target))) {
-		Action* const act = new Action(kStandardActionOpenMainMenu, _("Open main menu"));
+		act = new Action(kStandardActionOpenMainMenu, _("Open main menu"));
 		act->setCustomEngineActionEvent(kRivenActionOpenMainMenu);
 		act->addDefaultInputMapping("ESCAPE");
+		act->addDefaultInputMapping("JOY_X");
 		engineKeyMap->addAction(act);
 	}
 
-	struct ActionEntry {
-		const char *id;
-		const RivenAction action;
-		const char *defaultHwId;
-		const char *description;
-	};
-
-	const ActionEntry keyActionEntries[] = {
-		{ kStandardActionSkip,          kRivenActionSkip,              "ESCAPE",   _("Skip")                },
-		{ kStandardActionInteract,      kRivenActionInteract,          "RETURN",   _("Interact")            },
-		{ "LOAD",                       kRivenActionLoadGameState,     "C+o",      _("Load game state")     },
-		{ "SAVE",                       kRivenActionSaveGameState,     "C+s",      _("Save game state")     },
-		{ "OPTS",                       kRivenActionOpenOptionsDialog, "F5",       _("Show options menu")   },
-		{ kStandardActionPause,         kRivenActionPause,             "SPACE",    _("Pause")               },
-		{ kStandardActionMoveForward,   kRivenActionMoveForward,       "UP",       _("Move forward")        },
-		{ "FWDL",                       kRivenActionMoveForwardLeft,   "",         _("Move forward left")   },
-		{ "FWDR",                       kRivenActionMoveForwardRight,  "",         _("Move forward right")  },
-		{ kStandardActionMoveBackwards, kRivenActionMoveBack,          "DOWN",     _("Move backwards")      },
-		{ kStandardActionTurnLeft,      kRivenActionMoveLeft,          "LEFT",     _("Turn left")           },
-		{ kStandardActionTurnRight,     kRivenActionMoveRight,         "RIGHT",    _("Turn right")          },
-		{ kStandardActionMoveUpwards,   kRivenActionLookUp,            "PAGEUP",   _("Look up")             },
-		{ kStandardActionMoveDownwards, kRivenActionLookDown,          "PAGEDOWN", _("Look down")           },
-		{ kStandardActionOpenDebugger,  kRivenActionOpenDebugger,      "C+d",      _("Open debugger")       }
-	};
-
-	const ActionEntry keyActionEntriesDemo[] = {
-		{ kStandardActionOpenMainMenu,  kRivenActionOpenMainMenu,      "C+r",      _("Return to main menu") },
-		{ "INTV",                       kRivenActionPlayIntroVideos,   "C+p",      _("Play intro videos")   }
-	};
+	act = new Action(kStandardActionSkip, _("Skip"));
+	act->setCustomEngineActionEvent(kRivenActionSkip);
+	act->addDefaultInputMapping("ESCAPE");
+	act->addDefaultInputMapping("JOY_Y");
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionInteract, _("Interact"));
+	act->setCustomEngineActionEvent(kRivenActionInteract);
+	act->addDefaultInputMapping("MOUSE_LEFT");
+	act->addDefaultInputMapping("JOY_A");
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionLoad, _("Load game state"));
+	act->setCustomEngineActionEvent(kRivenActionLoadGameState);
+	act->addDefaultInputMapping("C+o");
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionSave, _("Save game state"));
+	act->setCustomEngineActionEvent(kRivenActionSaveGameState);
+	act->addDefaultInputMapping("C+s");
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionOpenSettings, _("Show options menu"));
+	act->setCustomEngineActionEvent(kRivenActionOpenOptionsDialog);
+	act->addDefaultInputMapping("F5");
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionPause, _("Pause"));
+	act->setCustomEngineActionEvent(kRivenActionPause);
+	act->addDefaultInputMapping("SPACE");
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionMoveUp, _("Move forward"));
+	act->setCustomEngineActionEvent(kRivenActionMoveForward);
+	act->addDefaultInputMapping("UP");
+	act->addDefaultInputMapping("JOY_UP");
+	engineKeyMap->addAction(act);
+
+	act = new Action("FWDL", _("Move forward left"));
+	act->setCustomEngineActionEvent(kRivenActionMoveForwardLeft);
+	engineKeyMap->addAction(act);
+
+	act = new Action("FWDR", _("Move forward right"));
+	act->setCustomEngineActionEvent(kRivenActionMoveForwardRight);
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionMoveDown, _("Move backwards"));
+	act->setCustomEngineActionEvent(kRivenActionMoveBack);
+	act->addDefaultInputMapping("DOWN");
+	act->addDefaultInputMapping("JOY_DOWN");
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionMoveLeft, _("Turn left"));
+	act->setCustomEngineActionEvent(kRivenActionMoveLeft);
+	act->addDefaultInputMapping("LEFT");
+	act->addDefaultInputMapping("JOY_LEFT");
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionMoveRight, _("Turn right"));
+	act->setCustomEngineActionEvent(kRivenActionMoveRight);
+	act->addDefaultInputMapping("RIGHT");
+	act->addDefaultInputMapping("JOY_RIGHT");
+	engineKeyMap->addAction(act);
+
+	act = new Action("LKUP", _("Look up"));
+	act->setCustomEngineActionEvent(kRivenActionMoveRight);
+	act->addDefaultInputMapping("PAGEUP");
+	engineKeyMap->addAction(act);
+
+	act = new Action("LKDN", _("Look down"));
+	act->setCustomEngineActionEvent(kRivenActionMoveRight);
+	act->addDefaultInputMapping("PAGEDOWN");
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionOpenDebugger, _("Open debugger"));
+	act->setCustomEngineActionEvent(kRivenActionOpenDebugger);
+	act->addDefaultInputMapping("C+d");
+	engineKeyMap->addAction(act);
 
-	for (uint i = 0; i < ARRAYSIZE(keyActionEntries); i++) {
-		Action *act = new Action(keyActionEntries[i].id, keyActionEntries[i].description);
-		act->setCustomEngineActionEvent(keyActionEntries[i].action);
-		act->addDefaultInputMapping(keyActionEntries[i].defaultHwId);
+	if (checkGameGUIOption(GAMEOPTION_DEMO, ConfMan.get("guioptions", target))) {
+		act = new Action(kStandardActionOpenMainMenu, _("Return to main menu"));
+		act->setCustomEngineActionEvent(kRivenActionOpenMainMenu);
+		act->addDefaultInputMapping("C+r");
 		engineKeyMap->addAction(act);
-	}
 
-	if (checkGameGUIOption(GAMEOPTION_DEMO, ConfMan.get("guioptions", target))) {
-		for (uint i = 0; i < ARRAYSIZE(keyActionEntriesDemo); i++) {
-			Action *act = new Action(keyActionEntriesDemo[i].id, keyActionEntriesDemo[i].description);
-			act->setCustomEngineActionEvent(keyActionEntriesDemo[i].action);
-			act->addDefaultInputMapping(keyActionEntriesDemo[i].defaultHwId);
-			engineKeyMap->addAction(act);
-		}
+		act = new Action("INTV", _("Play intro videos"));
+		act->setCustomEngineActionEvent(kRivenActionPlayIntroVideos);
+		act->addDefaultInputMapping("C+p");
+		engineKeyMap->addAction(act);
 	}
 
 	return Keymap::arrayOf(engineKeyMap);
diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp
index 0b16e01..ac95dd2 100644
--- a/engines/pegasus/pegasus.cpp
+++ b/engines/pegasus/pegasus.cpp
@@ -2496,35 +2496,35 @@ Common::KeymapArray PegasusEngine::initKeymaps() {
 
 	Action *act;
 
-	act = new Action(kStandardActionMoveForward, _("Up/Zoom In/Move Forward/Open Doors"));
+	act = new Action(kStandardActionMoveUp, _("Up/Zoom In/Move Forward/Open Doors"));
 	act->setCustomEngineActionEvent(kPegasusActionUp);
 	act->addDefaultInputMapping("UP");
 	act->addDefaultInputMapping("KP8");
 	act->addDefaultInputMapping("JOY_UP");
 	engineKeyMap->addAction(act);
 
-	act = new Action(kStandardActionMoveBackwards, _("Down/Zoom Out"));
+	act = new Action(kStandardActionMoveDown, _("Down/Zoom Out"));
 	act->setCustomEngineActionEvent(kPegasusActionDown);
 	act->addDefaultInputMapping("DOWN");
 	act->addDefaultInputMapping("KP5");
 	act->addDefaultInputMapping("JOY_DOWN");
 	engineKeyMap->addAction(act);
 
-	act = new Action(kStandardActionTurnLeft, _("Turn Left"));
+	act = new Action(kStandardActionMoveLeft, _("Turn Left"));
 	act->setCustomEngineActionEvent(kPegasusActionLeft);
 	act->addDefaultInputMapping("LEFT");
 	act->addDefaultInputMapping("KP4");
 	act->addDefaultInputMapping("JOY_LEFT");
 	engineKeyMap->addAction(act);
 
-	act = new Action(kStandardActionTurnRight, _("Turn Right"));
+	act = new Action(kStandardActionMoveRight, _("Turn Right"));
 	act->setCustomEngineActionEvent(kPegasusActionRight);
 	act->addDefaultInputMapping("RIGHT");
 	act->addDefaultInputMapping("KP6");
 	act->addDefaultInputMapping("JOY_RIGHT");
 	engineKeyMap->addAction(act);
 
-	act = new Action("ENT", _("Action/Select"));
+	act = new Action(kStandardActionInteract, _("Action/Select"));
 	act->setCustomEngineActionEvent(kPegasusActionInteract);
 	act->addDefaultInputMapping("SPACE");
 	act->addDefaultInputMapping("RETURN");
@@ -2573,7 +2573,7 @@ Common::KeymapArray PegasusEngine::initKeymaps() {
 	act->addDefaultInputMapping("JOY_X");
 	engineKeyMap->addAction(act);
 
-	act = new Action("PM", _("Display/Hide Pause Menu"));
+	act = new Action(kStandardActionOpenMainMenu, _("Display/Hide Pause Menu"));
 	act->setCustomEngineActionEvent(kPegasusActionShowPauseMenu);
 	act->addDefaultInputMapping("p");
 	act->addDefaultInputMapping("ESCAPE");
@@ -2595,13 +2595,13 @@ Common::KeymapArray PegasusEngine::initKeymaps() {
 	engineKeyMap->addAction(act);
 
 	// We support meta where available and control elsewhere
-	act = new Action("SAVE", _("Save Game"));
+	act = new Action(kStandardActionSave, _("Save Game"));
 	act->setCustomEngineActionEvent(kPegasusActionSaveGameState);
 	act->addDefaultInputMapping("C+s");
 	act->addDefaultInputMapping("M+s");
 	engineKeyMap->addAction(act);
 
-	act = new Action("LOAD", _("Load Game"));
+	act = new Action(kStandardActionLoad, _("Load Game"));
 	act->setCustomEngineActionEvent(kPegasusActionLoadGameState);
 	act->addDefaultInputMapping("C+o"); // o for open (original)
 	act->addDefaultInputMapping("M+o");


Commit: c001094bce1cda0ed1239cc217fb53c45803a735
    https://github.com/scummvm/scummvm/commit/c001094bce1cda0ed1239cc217fb53c45803a735
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
KEYMAPPER: Add a button in the remap dialog to reset an entire keymap

Changed paths:
    backends/keymapper/remap-widget.cpp
    backends/keymapper/remap-widget.h


diff --git a/backends/keymapper/remap-widget.cpp b/backends/keymapper/remap-widget.cpp
index cbf2a54..73a1779 100644
--- a/backends/keymapper/remap-widget.cpp
+++ b/backends/keymapper/remap-widget.cpp
@@ -37,11 +37,12 @@
 namespace Common {
 
 enum {
-	kRemapCmd  = 'REMP',
-	kClearCmd  = 'CLER',
-	kResetCmd  = 'RSET',
-	kCloseCmd  = 'CLOS',
-	kReflowCmd = 'REFL'
+	kRemapCmd        = 'REMP',
+	kClearCmd        = 'CLER',
+	kResetActionCmd  = 'RTAC',
+	kResetKeymapCmd  = 'RTKM',
+	kCloseCmd        = 'CLOS',
+	kReflowCmd       = 'REFL'
 };
 
 RemapWidget::RemapWidget(GuiObject *boss, const Common::String &name, const KeymapArray &keymaps) :
@@ -119,8 +120,13 @@ void RemapWidget::reflowActionWidgets() {
 			// Insert a keymap separator
 			x = 4 * spacing + keyButtonWidth + 2 * clearButtonWidth;
 
-			GUI::StaticTextWidget *serarator = _keymapSeparators[row.keymap];
-			serarator->resize(x, y, getWidth() - x - spacing, kLineHeight);
+			KeymapTitleRow keymapTitle = _keymapSeparators[row.keymap];
+			if (keymapTitle.descriptionText) {
+				uint descriptionWidth = getWidth() - x - spacing - keyButtonWidth - spacing;
+
+				keymapTitle.descriptionText->resize(x, y, descriptionWidth, kLineHeight);
+				keymapTitle.resetButton->resize(x + descriptionWidth, y, keyButtonWidth, buttonHeight);
+			}
 
 			y += kLineHeight + spacing;
 		}
@@ -149,8 +155,10 @@ void RemapWidget::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 d
 		startRemapping(cmd - kRemapCmd);
 	} else if (cmd >= kClearCmd && cmd < kClearCmd + _actions.size()) {
 		clearMapping(cmd - kClearCmd);
-	} else if (cmd >= kResetCmd && cmd < kResetCmd + _actions.size()) {
-		resetMapping(cmd - kResetCmd);
+	} else if (cmd >= kResetActionCmd && cmd < kResetActionCmd + _actions.size()) {
+		resetMapping(cmd - kResetActionCmd);
+	} else if (cmd >= kResetKeymapCmd && cmd < kResetKeymapCmd + _actions.size()) {
+		resetKeymap(cmd - kResetKeymapCmd);
 	} else if (cmd == kReflowCmd) {
 		reflowActionWidgets();
 	} else {
@@ -158,10 +166,10 @@ void RemapWidget::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 d
 	}
 }
 
-void RemapWidget::clearMapping(uint i) {
-	debug(3, "clear the mapping %u", i);
-	Action *action = _actions[i].action;
-	Keymap *keymap = _actions[i].keymap;
+void RemapWidget::clearMapping(uint actionIndex) {
+	debug(3, "clear the mapping %u", actionIndex);
+	Action *action = _actions[actionIndex].action;
+	Keymap *keymap = _actions[actionIndex].keymap;
 	keymap->unregisterMapping(action);
 
 	_changes = true;
@@ -170,10 +178,10 @@ void RemapWidget::clearMapping(uint i) {
 	refreshKeymap();
 }
 
-void RemapWidget::resetMapping(uint i) {
-	debug(3, "Reset the mapping %u", i);
-	Action *action = _actions[i].action;
-	Keymap *keymap = _actions[i].keymap;
+void RemapWidget::resetMapping(uint actionIndex) {
+	debug(3, "Reset the mapping %u", actionIndex);
+	Action *action = _actions[actionIndex].action;
+	Keymap *keymap = _actions[actionIndex].keymap;
 	keymap->resetMapping(action);
 
 	_changes = true;
@@ -182,21 +190,38 @@ void RemapWidget::resetMapping(uint i) {
 	refreshKeymap();
 }
 
-void RemapWidget::startRemapping(uint i) {
+void RemapWidget::resetKeymap(uint actionIndex) {
+	debug(3, "Reset the keymap %u", actionIndex);
+	Keymap *keymap = _actions[actionIndex].keymap;
+
+	for (uint i = 0; i < _actions.size(); i++) {
+		ActionRow &row = _actions[i];
+		if (row.keymap == keymap) {
+			keymap->resetMapping(row.action);
+		}
+	}
+
+	_changes = true;
+
+	stopRemapping();
+	refreshKeymap();
+}
+
+void RemapWidget::startRemapping(uint actionIndex) {
 	if (_remapInputWatcher->isWatching()) {
 		// Handle a second click on the button as a stop to remapping
 		stopRemapping();
 		return;
 	}
 
-	_remapKeymap = _actions[i].keymap;
-	_remapAction = _actions[i].action;
+	_remapKeymap = _actions[actionIndex].keymap;
+	_remapAction = _actions[actionIndex].action;
 	_remapTimeout = g_system->getMillis() + kRemapTimeoutDelay;
 	_remapInputWatcher->startWatching();
 
-	_actions[i].keyButton->setLabel("...");
-	_actions[i].keyButton->setTooltip("");
-	_actions[i].keyButton->markAsDirty();
+	_actions[actionIndex].keyButton->setLabel("...");
+	_actions[actionIndex].keyButton->setTooltip("");
+	_actions[actionIndex].keyButton->markAsDirty();
 }
 
 void RemapWidget::stopRemapping() {
@@ -253,9 +278,9 @@ void RemapWidget::refreshKeymap() {
 
 		if (!row.actionText) {
 			row.actionText = new GUI::StaticTextWidget(_scrollContainer, 0, 0, 0, 0, "", Graphics::kTextAlignLeft, nullptr, GUI::ThemeEngine::kFontStyleNormal);
-			row.keyButton = new GUI::ButtonWidget(_scrollContainer, 0, 0, 0, 0, "", 0, kRemapCmd + i);
+			row.keyButton = new GUI::ButtonWidget(_scrollContainer, 0, 0, 0, 0, "", nullptr, kRemapCmd + i);
 			row.clearButton = addClearButton(_scrollContainer, "", kClearCmd + i, 0, 0, clearButtonWidth, clearButtonHeight);
-			row.resetButton = new GUI::ButtonWidget(_scrollContainer, 0, 0, 0, 0, "", 0, kResetCmd + i);
+			row.resetButton = new GUI::ButtonWidget(_scrollContainer, 0, 0, 0, 0, "", nullptr, kResetActionCmd + i);
 		}
 
 		row.actionText->setLabel(row.action->description);
@@ -283,8 +308,14 @@ void RemapWidget::refreshKeymap() {
 		row.resetButton->setLabel(_("R"));
 		row.resetButton->setTooltip(_("Reset to defaults"));
 
-		if (!_keymapSeparators.contains(row.keymap)) {
-			_keymapSeparators[row.keymap] = new GUI::StaticTextWidget(_scrollContainer, 0, 0, 0, 0, row.keymap->getDescription(), Graphics::kTextAlignLeft);
+		KeymapTitleRow &keymapTitle = _keymapSeparators[row.keymap];
+		if (!keymapTitle.descriptionText) {
+			keymapTitle.descriptionText = new GUI::StaticTextWidget(_scrollContainer, 0, 0, 0, 0, row.keymap->getDescription(), Graphics::kTextAlignLeft);
+			keymapTitle.resetButton = new GUI::ButtonWidget(_scrollContainer, 0, 0, 0, 0, "", nullptr, kResetKeymapCmd + i);
+
+			// I18N: Button to reset keymap mappings to defaults
+			keymapTitle.resetButton->setLabel(_("Reset"));
+			keymapTitle.resetButton->setTooltip(_("Reset to defaults"));
 		}
 	}
 }
diff --git a/backends/keymapper/remap-widget.h b/backends/keymapper/remap-widget.h
index 4fe97cf..4f7a862 100644
--- a/backends/keymapper/remap-widget.h
+++ b/backends/keymapper/remap-widget.h
@@ -67,6 +67,13 @@ protected:
 		ActionRow() : keymap(nullptr), action(nullptr), actionText(nullptr), keyButton(nullptr), clearButton(nullptr), resetButton(nullptr) { }
 	};
 
+	struct KeymapTitleRow {
+		GUI::StaticTextWidget *descriptionText;
+		GUI::ButtonWidget *resetButton;
+
+		KeymapTitleRow() : descriptionText(nullptr), resetButton(nullptr) {}
+	};
+
 	void drawWidget() override {}
 	void reflowLayout() override;
 	Widget *findWidget(int x, int y) override;
@@ -74,9 +81,10 @@ protected:
 	void loadKeymap();
 	void refreshKeymap();
 	void reflowActionWidgets();
-	void clearMapping(uint i);
-	void resetMapping(uint i);
-	void startRemapping(uint i);
+	void clearMapping(uint actionIndex);
+	void resetMapping(uint actionIndex);
+	void resetKeymap(uint actionIndex);
+	void startRemapping(uint actionIndex);
 	void stopRemapping();
 
 	KeymapArray _keymapTable;
@@ -93,7 +101,7 @@ protected:
 	bool _changes;
 
 	Array<ActionRow> _actions;
-	HashMap<Keymap *, GUI::StaticTextWidget *> _keymapSeparators;
+	HashMap<Keymap *, KeymapTitleRow> _keymapSeparators;
 };
 
 } // End of namespace Common


Commit: 17a13c929492a4f96b81ab58a35e5ab436937406
    https://github.com/scummvm/scummvm/commit/17a13c929492a4f96b81ab58a35e5ab436937406
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
KEYMAPPER: Shorten the name of some joystick inputs

So they fit more easily in the remap dialog

Changed paths:
    backends/keymapper/hardware-input.cpp


diff --git a/backends/keymapper/hardware-input.cpp b/backends/keymapper/hardware-input.cpp
index ce14c5f..e671c92 100644
--- a/backends/keymapper/hardware-input.cpp
+++ b/backends/keymapper/hardware-input.cpp
@@ -225,22 +225,22 @@ const HardwareInputTableEntry defaultMouseButtons[] = {
 };
 
 const HardwareInputTableEntry defaultJoystickButtons[] = {
-    { "JOY_A",              JOYSTICK_BUTTON_A,              _s("Joy A")              },
-    { "JOY_B",              JOYSTICK_BUTTON_B,              _s("Joy B")              },
-    { "JOY_X",              JOYSTICK_BUTTON_X,              _s("Joy X")              },
-    { "JOY_Y",              JOYSTICK_BUTTON_Y,              _s("Joy Y")              },
-    { "JOY_BACK",           JOYSTICK_BUTTON_BACK,           _s("Joy Back")           },
-    { "JOY_GUIDE",          JOYSTICK_BUTTON_GUIDE,          _s("Joy Guide")          },
-    { "JOY_START",          JOYSTICK_BUTTON_START,          _s("Joy Start")          },
-    { "JOY_LEFT_STICK",     JOYSTICK_BUTTON_LEFT_STICK,     _s("Joy Left Stick")     },
-    { "JOY_RIGHT_STICK",    JOYSTICK_BUTTON_RIGHT_STICK,    _s("Joy Right Stick")    },
-    { "JOY_LEFT_SHOULDER",  JOYSTICK_BUTTON_LEFT_SHOULDER,  _s("Joy Left Shoulder")  },
-    { "JOY_RIGHT_SHOULDER", JOYSTICK_BUTTON_RIGHT_SHOULDER, _s("Joy Right Shoulder") },
-    { "JOY_UP",             JOYSTICK_BUTTON_DPAD_UP,        _s("Joy D-pad Up")       },
-    { "JOY_DOWN",           JOYSTICK_BUTTON_DPAD_DOWN,      _s("Joy D-pad Down")     },
-    { "JOY_LEFT",           JOYSTICK_BUTTON_DPAD_LEFT,      _s("Joy D-pad Left")     },
-    { "JOY_RIGHT",          JOYSTICK_BUTTON_DPAD_RIGHT,     _s("Joy D-pad Right")    },
-    { nullptr,              0,                              nullptr                 }
+    { "JOY_A",              JOYSTICK_BUTTON_A,              _s("Joy A")          },
+    { "JOY_B",              JOYSTICK_BUTTON_B,              _s("Joy B")          },
+    { "JOY_X",              JOYSTICK_BUTTON_X,              _s("Joy X")          },
+    { "JOY_Y",              JOYSTICK_BUTTON_Y,              _s("Joy Y")          },
+    { "JOY_BACK",           JOYSTICK_BUTTON_BACK,           _s("Joy Back")       },
+    { "JOY_GUIDE",          JOYSTICK_BUTTON_GUIDE,          _s("Joy Guide")      },
+    { "JOY_START",          JOYSTICK_BUTTON_START,          _s("Joy Start")      },
+    { "JOY_LEFT_STICK",     JOYSTICK_BUTTON_LEFT_STICK,     _s("Left Stick")     },
+    { "JOY_RIGHT_STICK",    JOYSTICK_BUTTON_RIGHT_STICK,    _s("Right Stick")    },
+    { "JOY_LEFT_SHOULDER",  JOYSTICK_BUTTON_LEFT_SHOULDER,  _s("Left Shoulder")  },
+    { "JOY_RIGHT_SHOULDER", JOYSTICK_BUTTON_RIGHT_SHOULDER, _s("Right Shoulder") },
+    { "JOY_UP",             JOYSTICK_BUTTON_DPAD_UP,        _s("D-pad Up")       },
+    { "JOY_DOWN",           JOYSTICK_BUTTON_DPAD_DOWN,      _s("D-pad Down")     },
+    { "JOY_LEFT",           JOYSTICK_BUTTON_DPAD_LEFT,      _s("D-pad Left")     },
+    { "JOY_RIGHT",          JOYSTICK_BUTTON_DPAD_RIGHT,     _s("D-pad Right")    },
+    { nullptr,              0,                              nullptr              }
 };
 
 HardwareInputSet::~HardwareInputSet() {


Commit: 5079fa9dd41458939a508724136b52b6cbeadde8
    https://github.com/scummvm/scummvm/commit/5079fa9dd41458939a508724136b52b6cbeadde8
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:29+01:00

Commit Message:
KEYMAPPER: Sort the mappings by type and id in the remap dialog

Changed paths:
    backends/keymapper/keymap.cpp


diff --git a/backends/keymapper/keymap.cpp b/backends/keymapper/keymap.cpp
index 84b939b..8dd795a 100644
--- a/backends/keymapper/keymap.cpp
+++ b/backends/keymapper/keymap.cpp
@@ -88,6 +88,15 @@ void Keymap::resetMapping(Action *action) {
 	registerMappings(action, hwInputIds);
 }
 
+struct HardwareInputTypeIdComparator {
+	bool operator()(const HardwareInput &x, const HardwareInput &y) const {
+		if (x.type != y.type) {
+			return x.type < y.type;
+		}
+		return x.id.compareTo(y.id);
+	}
+};
+
 Array<HardwareInput> Keymap::getActionMapping(Action *action) const {
 	Array<HardwareInput> inputs;
 
@@ -100,6 +109,9 @@ Array<HardwareInput> Keymap::getActionMapping(Action *action) const {
 		}
 	}
 
+	// Sort the inputs by type and then id for the remap dialog
+	Common::sort(inputs.begin(), inputs.end(), HardwareInputTypeIdComparator());
+
 	return inputs;
 }
 


Commit: cc15496e9e700218aa7aa3c1bd93b36fe4b6ee09
    https://github.com/scummvm/scummvm/commit/cc15496e9e700218aa7aa3c1bd93b36fe4b6ee09
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:30+01:00

Commit Message:
KEYMAPPER: Use a dropdown button to save horizontal space

Changed paths:
    backends/keymapper/hardware-input.cpp
    backends/keymapper/remap-widget.cpp
    backends/keymapper/remap-widget.h
    gui/themes/default.inc
    gui/themes/scummclassic.zip
    gui/themes/scummclassic/classic_layout.stx
    gui/themes/scummclassic/classic_layout_lowres.stx
    gui/themes/scummmodern.zip
    gui/themes/scummmodern/scummmodern_layout.stx
    gui/themes/scummmodern/scummmodern_layout_lowres.stx
    gui/themes/scummremastered.zip
    gui/themes/scummremastered/remastered_layout.stx
    gui/themes/scummremastered/remastered_layout_lowres.stx


diff --git a/backends/keymapper/hardware-input.cpp b/backends/keymapper/hardware-input.cpp
index e671c92..0b4c0f5 100644
--- a/backends/keymapper/hardware-input.cpp
+++ b/backends/keymapper/hardware-input.cpp
@@ -214,7 +214,7 @@ const ModifierTableEntry defaultModifiers[] = {
 	{ KBD_SHIFT, "S", "Shift+" },
 	{ KBD_ALT,   "A", "Alt+"   },
 	{ KBD_META,  "M", "Meta+"  },
-	{ 0,     nullptr, nullptr }
+	{ 0,     nullptr, nullptr  }
 };
 
 const HardwareInputTableEntry defaultMouseButtons[] = {
diff --git a/backends/keymapper/remap-widget.cpp b/backends/keymapper/remap-widget.cpp
index 73a1779..1f8f5e7 100644
--- a/backends/keymapper/remap-widget.cpp
+++ b/backends/keymapper/remap-widget.cpp
@@ -98,12 +98,10 @@ void RemapWidget::reflowActionWidgets() {
 
 	int spacing = g_gui.xmlEval()->getVar("Globals.KeyMapper.Spacing");
 	int keyButtonWidth = g_gui.xmlEval()->getVar("Globals.KeyMapper.ButtonWidth");
-	int clearButtonWidth = g_gui.xmlEval()->getVar("Globals.Line.Height");
-	int clearButtonHeight = g_gui.xmlEval()->getVar("Globals.Line.Height");
-	int labelWidth = getWidth() - (spacing + keyButtonWidth + spacing + clearButtonWidth + spacing);
+	int resetButtonWidth = g_gui.xmlEval()->getVar("Globals.KeyMapper.ResetWidth");
+	int labelWidth = getWidth() - (spacing + keyButtonWidth + spacing);
 
 	uint textYOff = (buttonHeight - kLineHeight) / 2;
-	uint clearButtonYOff = (buttonHeight - clearButtonHeight) / 2;
 
 	uint y = spacing;
 
@@ -118,17 +116,17 @@ void RemapWidget::reflowActionWidgets() {
 			previousKeymap = row.keymap;
 
 			// Insert a keymap separator
-			x = 4 * spacing + keyButtonWidth + 2 * clearButtonWidth;
+			x = 2 * spacing + keyButtonWidth;
 
 			KeymapTitleRow keymapTitle = _keymapSeparators[row.keymap];
 			if (keymapTitle.descriptionText) {
-				uint descriptionWidth = getWidth() - x - spacing - keyButtonWidth - spacing;
+				uint descriptionWidth = getWidth() - x - spacing - resetButtonWidth - spacing;
 
-				keymapTitle.descriptionText->resize(x, y, descriptionWidth, kLineHeight);
-				keymapTitle.resetButton->resize(x + descriptionWidth, y, keyButtonWidth, buttonHeight);
+				keymapTitle.descriptionText->resize(x, y + textYOff, descriptionWidth, kLineHeight);
+				keymapTitle.resetButton->resize(x + descriptionWidth, y, resetButtonWidth, buttonHeight);
 			}
 
-			y += kLineHeight + spacing;
+			y += buttonHeight + spacing;
 		}
 
 		x = spacing;
@@ -136,12 +134,6 @@ void RemapWidget::reflowActionWidgets() {
 		row.keyButton->resize(x, y, keyButtonWidth, buttonHeight);
 
 		x += keyButtonWidth + spacing;
-		row.clearButton->resize(x, y + clearButtonYOff, clearButtonWidth, clearButtonHeight);
-
-		x += clearButtonWidth + spacing;
-		row.resetButton->resize(x, y + clearButtonYOff, clearButtonWidth, clearButtonHeight);
-
-		x += clearButtonWidth + spacing;
 		row.actionText->resize(x, y + textYOff, labelWidth, kLineHeight);
 
 		y += buttonHeight + spacing;
@@ -270,20 +262,17 @@ void RemapWidget::loadKeymap() {
 }
 
 void RemapWidget::refreshKeymap() {
-	int clearButtonWidth = g_gui.xmlEval()->getVar("Globals.Line.Height");
-	int clearButtonHeight = g_gui.xmlEval()->getVar("Globals.Line.Height");
-
 	for (uint i = 0; i < _actions.size(); i++) {
 		ActionRow &row = _actions[i];
 
 		if (!row.actionText) {
 			row.actionText = new GUI::StaticTextWidget(_scrollContainer, 0, 0, 0, 0, "", Graphics::kTextAlignLeft, nullptr, GUI::ThemeEngine::kFontStyleNormal);
-			row.keyButton = new GUI::ButtonWidget(_scrollContainer, 0, 0, 0, 0, "", nullptr, kRemapCmd + i);
-			row.clearButton = addClearButton(_scrollContainer, "", kClearCmd + i, 0, 0, clearButtonWidth, clearButtonHeight);
-			row.resetButton = new GUI::ButtonWidget(_scrollContainer, 0, 0, 0, 0, "", nullptr, kResetActionCmd + i);
-		}
+			row.actionText->setLabel(row.action->description);
 
-		row.actionText->setLabel(row.action->description);
+			row.keyButton = new GUI::DropdownButtonWidget(_scrollContainer, 0, 0, 0, 0, "", nullptr, kRemapCmd + i);
+			row.keyButton->appendEntry(_("Reset to defaults"), kResetActionCmd + i);
+			row.keyButton->appendEntry(_("Clear mapping"), kClearCmd + i);
+		}
 
 		Array<HardwareInput> mappedInputs = row.keymap->getActionMapping(row.action);
 
@@ -304,10 +293,6 @@ void RemapWidget::refreshKeymap() {
 			row.keyButton->setTooltip("");
 		}
 
-		// I18N: Button to reset key mapping to defaults
-		row.resetButton->setLabel(_("R"));
-		row.resetButton->setTooltip(_("Reset to defaults"));
-
 		KeymapTitleRow &keymapTitle = _keymapSeparators[row.keymap];
 		if (!keymapTitle.descriptionText) {
 			keymapTitle.descriptionText = new GUI::StaticTextWidget(_scrollContainer, 0, 0, 0, 0, row.keymap->getDescription(), Graphics::kTextAlignLeft);
diff --git a/backends/keymapper/remap-widget.h b/backends/keymapper/remap-widget.h
index 4f7a862..684575a 100644
--- a/backends/keymapper/remap-widget.h
+++ b/backends/keymapper/remap-widget.h
@@ -30,6 +30,7 @@
 
 namespace GUI {
 class ButtonWidget;
+class DropdownButtonWidget;
 class PopUpWidget;
 class ScrollContainerWidget;
 class StaticTextWidget;
@@ -60,11 +61,9 @@ protected:
 		Common::Action *action;
 
 		GUI::StaticTextWidget *actionText;
-		GUI::ButtonWidget *keyButton;
-		GUI::ButtonWidget *clearButton;
-		GUI::ButtonWidget *resetButton;
+		GUI::DropdownButtonWidget *keyButton;
 
-		ActionRow() : keymap(nullptr), action(nullptr), actionText(nullptr), keyButton(nullptr), clearButton(nullptr), resetButton(nullptr) { }
+		ActionRow() : keymap(nullptr), action(nullptr), actionText(nullptr), keyButton(nullptr) {}
 	};
 
 	struct KeymapTitleRow {
diff --git a/gui/themes/default.inc b/gui/themes/default.inc
index 8972e70..b04cc78 100644
--- a/gui/themes/default.inc
+++ b/gui/themes/default.inc
@@ -929,8 +929,8 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
 "<def var='RecorderDialog.ExtInfo.Visible' value='1'/>"
 "<def var='OnScreenDialog.ShowPics' value='0'/>"
 "<def var='KeyMapper.Spacing' value='10'/>"
-"<def var='KeyMapper.LabelWidth' value='100'/>"
-"<def var='KeyMapper.ButtonWidth' value='80'/>"
+"<def var='KeyMapper.ButtonWidth' value='140'/>"
+"<def var='KeyMapper.ResetWidth' value='80'/>"
 "<def var='Tooltip.MaxWidth' value='200'/>"
 "<def var='Tooltip.XDelta' value='16'/> "
 "<def var='Tooltip.YDelta' value='16'/>"
@@ -2677,8 +2677,8 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
 "<def var='RecorderDialog.ExtInfo.Visible' value='0'/>"
 "<def var='OnScreenDialog.ShowPics' value='0'/>"
 "<def var='KeyMapper.Spacing' value='5'/>"
-"<def var='KeyMapper.LabelWidth' value='80'/>"
-"<def var='KeyMapper.ButtonWidth' value='60'/>"
+"<def var='KeyMapper.ButtonWidth' value='100'/>"
+"<def var='KeyMapper.ResetWidth' value='60'/>"
 "<def var='Tooltip.MaxWidth' value='70'/>"
 "<def var='Tooltip.XDelta' value='8'/> "
 "<def var='Tooltip.YDelta' value='8'/>"
diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip
index 662f4eb..a445617 100644
Binary files a/gui/themes/scummclassic.zip and b/gui/themes/scummclassic.zip differ
diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx
index a138a70..3b58fb0 100644
--- a/gui/themes/scummclassic/classic_layout.stx
+++ b/gui/themes/scummclassic/classic_layout.stx
@@ -41,8 +41,8 @@
 		<def var = 'OnScreenDialog.ShowPics' value = '0'/>
 
 		<def var = 'KeyMapper.Spacing' value = '10'/>
-		<def var = 'KeyMapper.LabelWidth' value = '100'/>
-		<def var = 'KeyMapper.ButtonWidth' value = '80'/>
+		<def var = 'KeyMapper.ButtonWidth' value = '140'/>
+		<def var = 'KeyMapper.ResetWidth' value = '80'/>
 
 		<def var = 'Tooltip.MaxWidth' value = '200'/>
 		<def var = 'Tooltip.XDelta' value = '16'/> <!-- basically cursor size -->
diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx
index ebd6c1f..74ef157 100644
--- a/gui/themes/scummclassic/classic_layout_lowres.stx
+++ b/gui/themes/scummclassic/classic_layout_lowres.stx
@@ -42,8 +42,8 @@
 		<def var = 'OnScreenDialog.ShowPics' value = '0'/>
 
 		<def var = 'KeyMapper.Spacing' value = '5'/>
-		<def var = 'KeyMapper.LabelWidth' value = '80'/>
-		<def var = 'KeyMapper.ButtonWidth' value = '60'/>
+		<def var = 'KeyMapper.ButtonWidth' value = '100'/>
+		<def var = 'KeyMapper.ResetWidth' value = '60'/>
 
 		<def var = 'Tooltip.MaxWidth' value = '70'/>
 		<def var = 'Tooltip.XDelta' value = '8'/> <!-- basically cursor size -->
diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index 18d5750..ac7d903 100644
Binary files a/gui/themes/scummmodern.zip and b/gui/themes/scummmodern.zip differ
diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx
index c2b8938..f4011a4 100644
--- a/gui/themes/scummmodern/scummmodern_layout.stx
+++ b/gui/themes/scummmodern/scummmodern_layout.stx
@@ -48,8 +48,8 @@
 		<def var = 'OnScreenDialog.ShowPics' value = '1'/>
 
 		<def var = 'KeyMapper.Spacing' value = '10'/>
-		<def var = 'KeyMapper.LabelWidth' value = '100'/>
-		<def var = 'KeyMapper.ButtonWidth' value = '80'/>
+		<def var = 'KeyMapper.ButtonWidth' value = '140'/>
+		<def var = 'KeyMapper.ResetWidth' value = '80'/>
 
 		<def var = 'Tooltip.MaxWidth' value = '200'/>
 		<def var = 'Tooltip.XDelta' value = '16'/> <!-- basically cursor size -->
diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
index 4bd8a23..b0c2b8d 100644
--- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx
+++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
@@ -57,8 +57,8 @@
 		/>
 
 		<def var = 'KeyMapper.Spacing' value = '5'/>
-		<def var = 'KeyMapper.LabelWidth' value = '80'/>
-		<def var = 'KeyMapper.ButtonWidth' value = '60'/>
+		<def var = 'KeyMapper.ButtonWidth' value = '100'/>
+		<def var = 'KeyMapper.ResetWidth' value = '60'/>
 
 		<def var = 'Tooltip.MaxWidth' value = '70'/>
 		<def var = 'Tooltip.XDelta' value = '9'/> <!-- basically cursor size -->
diff --git a/gui/themes/scummremastered.zip b/gui/themes/scummremastered.zip
index c3c64a9..0347860 100644
Binary files a/gui/themes/scummremastered.zip and b/gui/themes/scummremastered.zip differ
diff --git a/gui/themes/scummremastered/remastered_layout.stx b/gui/themes/scummremastered/remastered_layout.stx
index ba92d91..11e1bdb 100644
--- a/gui/themes/scummremastered/remastered_layout.stx
+++ b/gui/themes/scummremastered/remastered_layout.stx
@@ -48,8 +48,8 @@
 		<def var = 'OnScreenDialog.ShowPics' value = '1'/>
 
 		<def var = 'KeyMapper.Spacing' value = '10'/>
-		<def var = 'KeyMapper.LabelWidth' value = '100'/>
-		<def var = 'KeyMapper.ButtonWidth' value = '80'/>
+		<def var = 'KeyMapper.ButtonWidth' value = '140'/>
+		<def var = 'KeyMapper.ResetWidth' value = '80'/>
 
 		<def var = 'Tooltip.MaxWidth' value = '200'/>
 		<def var = 'Tooltip.XDelta' value = '16'/> <!-- basically cursor size -->
diff --git a/gui/themes/scummremastered/remastered_layout_lowres.stx b/gui/themes/scummremastered/remastered_layout_lowres.stx
index 818e725..e7963f5 100644
--- a/gui/themes/scummremastered/remastered_layout_lowres.stx
+++ b/gui/themes/scummremastered/remastered_layout_lowres.stx
@@ -57,8 +57,8 @@
 		/>
 
 		<def var = 'KeyMapper.Spacing' value = '5'/>
-		<def var = 'KeyMapper.LabelWidth' value = '80'/>
-		<def var = 'KeyMapper.ButtonWidth' value = '60'/>
+		<def var = 'KeyMapper.ButtonWidth' value = '100'/>
+		<def var = 'KeyMapper.ResetWidth' value = '60'/>
 
 		<def var = 'Tooltip.MaxWidth' value = '70'/>
 		<def var = 'Tooltip.XDelta' value = '9'/> <!-- basically cursor size -->


Commit: 5106563c65ed4e55de3edcee72753a8d32b27cf8
    https://github.com/scummvm/scummvm/commit/5106563c65ed4e55de3edcee72753a8d32b27cf8
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:30+01:00

Commit Message:
MOHAWK: MYST: Add a keymap

Changed paths:
    engines/mohawk/detection.cpp
    engines/mohawk/detection_tables.h
    engines/mohawk/myst.cpp
    engines/mohawk/myst.h


diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp
index c5bf935..6d749f5 100644
--- a/engines/mohawk/detection.cpp
+++ b/engines/mohawk/detection.cpp
@@ -121,7 +121,7 @@ bool MohawkEngine_Myst::hasFeature(EngineFeature f) const {
 	return
 		MohawkEngine::hasFeature(f)
 		|| (f == kSupportsLoadingDuringRuntime)
-		|| (f == kSupportsSavingDuringRuntime);
+	        || (f == kSupportsSavingDuringRuntime);
 }
 
 #endif
@@ -334,6 +334,11 @@ SaveStateDescriptor MohawkMetaEngine::querySaveMetaInfos(const char *target, int
 Common::KeymapArray MohawkMetaEngine::initKeymaps(const char *target) const {
 	Common::String gameId = ConfMan.get("gameid", target);
 
+#ifdef ENABLE_MYST
+	if (gameId == "myst" || gameId == "makingofmyst") {
+		return Mohawk::MohawkEngine_Myst::initKeymaps(target);
+	}
+#endif
 #ifdef ENABLE_RIVEN
 	if (gameId == "riven") {
 		return Mohawk::MohawkEngine_Riven::initKeymaps(target);
diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h
index 9ac74b5..94c5e31 100644
--- a/engines/mohawk/detection_tables.h
+++ b/engines/mohawk/detection_tables.h
@@ -24,12 +24,13 @@ namespace Mohawk {
 
 #define GUI_OPTIONS_MYST                   GUIO4(GUIO_NOASPECT, GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOMIDI)
 #define GUI_OPTIONS_MYST_ME                GUIO5(GUIO_NOASPECT, GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOMIDI, GAMEOPTION_PLAY_MYST_FLYBY)
+#define GUI_OPTIONS_MYST_ME_25TH           GUIO6(GUIO_NOASPECT, GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOMIDI, GAMEOPTION_PLAY_MYST_FLYBY, GAMEOPTION_25TH)
 #define GUI_OPTIONS_MYST_DEMO              GUIO4(GUIO_NOASPECT, GUIO_NOSUBTITLES, GUIO_NOMIDI, GUIO_NOLAUNCHLOAD)
 #define GUI_OPTIONS_MYST_MAKING_OF         GUIO5(GUIO_NOASPECT, GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOMIDI, GUIO_NOLAUNCHLOAD)
 
 #define GUI_OPTIONS_RIVEN                  GUIO4(GUIO_NOASPECT, GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOMIDI)
-#define GUI_OPTIONS_RIVEN_25TH             GUIO5(GUIO_NOASPECT, GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOMIDI, GUIO_GAMEOPTIONS2)
-#define GUI_OPTIONS_RIVEN_DEMO             GUIO6(GUIO_NOASPECT, GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOMIDI, GUIO_NOLAUNCHLOAD, GUIO_GAMEOPTIONS3)
+#define GUI_OPTIONS_RIVEN_25TH             GUIO5(GUIO_NOASPECT, GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOMIDI, GAMEOPTION_25TH)
+#define GUI_OPTIONS_RIVEN_DEMO             GUIO6(GUIO_NOASPECT, GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOMIDI, GUIO_NOLAUNCHLOAD, GAMEOPTION_DEMO)
 
 static const MohawkGameDescription gameDescriptions[] = {
 	// Myst
@@ -351,7 +352,7 @@ static const MohawkGameDescription gameDescriptions[] = {
 			Common::EN_ANY,
 			Common::kPlatformWindows,
 			ADGF_NO_FLAGS,
-			GUI_OPTIONS_MYST_ME
+			GUI_OPTIONS_MYST_ME_25TH
 		},
 		GType_MYST,
 		GF_ME | GF_25TH,
@@ -372,7 +373,7 @@ static const MohawkGameDescription gameDescriptions[] = {
 			Common::FR_FRA,
 			Common::kPlatformWindows,
 			ADGF_NO_FLAGS,
-			GUI_OPTIONS_MYST_ME
+			GUI_OPTIONS_MYST_ME_25TH
 		},
 		GType_MYST,
 		GF_ME | GF_25TH | GF_LANGUAGE_FILES,
@@ -393,7 +394,7 @@ static const MohawkGameDescription gameDescriptions[] = {
 			Common::DE_DEU,
 			Common::kPlatformWindows,
 			ADGF_NO_FLAGS,
-			GUI_OPTIONS_MYST_ME
+			GUI_OPTIONS_MYST_ME_25TH
 		},
 		GType_MYST,
 		GF_ME | GF_25TH | GF_LANGUAGE_FILES,
@@ -414,7 +415,7 @@ static const MohawkGameDescription gameDescriptions[] = {
 			Common::PL_POL,
 			Common::kPlatformWindows,
 			ADGF_NO_FLAGS,
-			GUI_OPTIONS_MYST_ME
+			GUI_OPTIONS_MYST_ME_25TH
 		},
 		GType_MYST,
 		GF_ME | GF_25TH | GF_LANGUAGE_FILES,
@@ -435,7 +436,7 @@ static const MohawkGameDescription gameDescriptions[] = {
 			Common::ES_ESP,
 			Common::kPlatformWindows,
 			ADGF_NO_FLAGS,
-			GUI_OPTIONS_MYST_ME
+			GUI_OPTIONS_MYST_ME_25TH
 		},
 		GType_MYST,
 		GF_ME | GF_25TH | GF_LANGUAGE_FILES,
diff --git a/engines/mohawk/myst.cpp b/engines/mohawk/myst.cpp
index 9d1a1e1..6367e34 100644
--- a/engines/mohawk/myst.cpp
+++ b/engines/mohawk/myst.cpp
@@ -20,8 +20,13 @@
  *
  */
 
+#include "backends/keymapper/action.h"
+#include "backends/keymapper/keymap.h"
+#include "backends/keymapper/standard-actions.h"
+
 #include "common/config-manager.h"
 #include "common/debug-channels.h"
+#include "common/gui_options.h"
 #include "common/system.h"
 #include "common/translation.h"
 #include "common/textconsole.h"
@@ -58,6 +63,17 @@
 
 namespace Mohawk {
 
+enum MystEventAction {
+	kMystActionOpenMainMenu,
+	kMystActionSkip,
+	kMystActionInteract,
+	kMystActionLoadGameState,
+	kMystActionSaveGameState,
+	kMystActionOpenOptionsDialog,
+	kMystActionPause,
+	kMystActionOpenDebugger
+};
+
 MohawkEngine_Myst::MohawkEngine_Myst(OSystem *syst, const MohawkGameDescription *gamedesc) :
 		MohawkEngine(syst, gamedesc) {
 	DebugMan.addDebugChannel(kDebugVariable, "Variable", "Track Variable Accesses");
@@ -488,6 +504,61 @@ void MohawkEngine_Myst::loadArchive(const char *archiveName, const char *languag
 	_mhk.push_back(archive);
 }
 
+Common::KeymapArray MohawkEngine_Myst::initKeymaps(const char *target) {
+	using namespace Common;
+
+	Keymap *engineKeyMap = new Keymap(Keymap::kKeymapTypeGame, "myst", "Myst");
+
+	Action *act;
+
+	if (checkGameGUIOption(GAMEOPTION_25TH, ConfMan.get("guioptions", target))) {
+		act = new Action(kStandardActionOpenMainMenu, _("Open main menu"));
+		act->setCustomEngineActionEvent(kMystActionOpenMainMenu);
+		act->addDefaultInputMapping("ESCAPE");
+		act->addDefaultInputMapping("JOY_X");
+		engineKeyMap->addAction(act);
+	}
+
+	act = new Action(kStandardActionSkip, _("Skip"));
+	act->setCustomEngineActionEvent(kMystActionSkip);
+	act->addDefaultInputMapping("ESCAPE");
+	act->addDefaultInputMapping("JOY_Y");
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionInteract, _("Interact"));
+	act->setCustomEngineActionEvent(kMystActionInteract);
+	act->addDefaultInputMapping("MOUSE_LEFT");
+	act->addDefaultInputMapping("JOY_A");
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionLoad, _("Load game state"));
+	act->setCustomEngineActionEvent(kMystActionLoadGameState);
+	act->addDefaultInputMapping("C+o");
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionSave, _("Save game state"));
+	act->setCustomEngineActionEvent(kMystActionSaveGameState);
+	act->addDefaultInputMapping("C+s");
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionOpenSettings, _("Show options menu"));
+	act->setCustomEngineActionEvent(kMystActionOpenOptionsDialog);
+	act->addDefaultInputMapping("F5");
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionPause, _("Pause"));
+	act->setCustomEngineActionEvent(kMystActionPause);
+	act->addDefaultInputMapping("SPACE");
+	engineKeyMap->addAction(act);
+
+	act = new Action(kStandardActionOpenDebugger, _("Open debugger"));
+	act->setCustomEngineActionEvent(kMystActionOpenDebugger);
+	act->addDefaultInputMapping("C+d");
+	engineKeyMap->addAction(act);
+
+	return Keymap::arrayOf(engineKeyMap);
+}
+
 void MohawkEngine_Myst::doFrame() {
 	// Update any background videos
 	_video->updateMovies();
@@ -504,82 +575,79 @@ void MohawkEngine_Myst::doFrame() {
 	Common::Event event;
 	while (_system->getEventManager()->pollEvent(event)) {
 		switch (event.type) {
-			case Common::EVENT_MOUSEMOVE:
-				_mouseMoved = true;
-				break;
-			case Common::EVENT_LBUTTONUP:
-				_mouseClicked = false;
+		case Common::EVENT_MOUSEMOVE:
+			_mouseMoved = true;
+			break;
+		case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
+			switch ((MystEventAction)event.customType) {
+			case kMystActionOpenDebugger:
+				_console->attach();
+				_console->onFrame();
 				break;
-			case Common::EVENT_LBUTTONDOWN:
+			case kMystActionInteract:
 				_mouseClicked = true;
 				break;
-			case Common::EVENT_KEYDOWN:
-				switch (event.kbd.keycode) {
-					case Common::KEYCODE_d:
-						if (event.kbd.flags & Common::KBD_CTRL) {
-							_console->attach();
-							_console->onFrame();
-						}
-						break;
-					case Common::KEYCODE_SPACE:
-						pauseGame();
-						break;
-					case Common::KEYCODE_F5:
-						runOptionsDialog();
-						break;
-					case Common::KEYCODE_ESCAPE:
-						if (_stack->getStackId() == kCreditsStack) {
-							// Don't allow going to the menu while the credits play
-							break;
-						}
+			case kMystActionPause:
+				pauseGame();
+				break;
+			case kMystActionOpenOptionsDialog:
+				runOptionsDialog();
+				break;
+			case kMystActionOpenMainMenu:
+				if (_stack->getStackId() == kCreditsStack) {
+					// Don't allow going to the menu while the credits play
+					break;
+				}
 
-						if (!isInteractive()) {
-							// Try to skip the currently playing video
-							_escapePressed = true;
-						} else if (_stack->getStackId() == kMenuStack) {
-							// If the menu is active and a game is loaded, go back to the game
-							if (_prevStack) {
-								resumeFromMainMenu();
-							}
-						} else if (getFeatures() & GF_25TH) {
-							// If the game is interactive, open the main menu
-							goToMainMenu();
-						}
-						break;
-					case Common::KEYCODE_o:
-						if (event.kbd.flags & Common::KBD_CTRL) {
-							if (canLoadGameStateCurrently()) {
-								runLoadDialog();
-							}
+				if (getFeatures() & GF_25TH && isInteractive()) {
+					if (_stack->getStackId() == kMenuStack) {
+						// If the menu is active and a game is loaded, go back to the game
+						if (_prevStack) {
+							resumeFromMainMenu();
 						}
-						break;
-					case Common::KEYCODE_s:
-						if (event.kbd.flags & Common::KBD_CTRL) {
-							if (canSaveGameStateCurrently()) {
-								runSaveDialog();
-							}
-						}
-						break;
-					default:
-						break;
+					} else {
+						// If the game is interactive, open the main menu
+						goToMainMenu();
+					}
+				}
+				break;
+			case kMystActionSkip:
+				if (!isInteractive()) {
+					// Try to skip the currently playing video
+					_escapePressed = true;
+				}
+				break;
+			case kMystActionLoadGameState:
+				if (canLoadGameStateCurrently()) {
+					runLoadDialog();
 				}
 				break;
-			case Common::EVENT_KEYUP:
-				switch (event.kbd.keycode) {
-					case Common::KEYCODE_ESCAPE:
-						_escapePressed = false;
-						break;
-					default:
-						break;
+			case kMystActionSaveGameState:
+				if (canSaveGameStateCurrently()) {
+					runSaveDialog();
 				}
 				break;
-			case Common::EVENT_QUIT:
-			case Common::EVENT_RTL:
-				// Attempt to autosave before exiting
-				tryAutoSaving();
+			}
+			break;
+		case Common::EVENT_CUSTOM_ENGINE_ACTION_END:
+			switch ((MystEventAction)event.customType) {
+			case kMystActionInteract:
+				_mouseClicked = false;
+				break;
+			case kMystActionSkip:
+				_escapePressed = false;
 				break;
 			default:
 				break;
+			}
+			break;
+		case Common::EVENT_QUIT:
+		case Common::EVENT_RTL:
+			// Attempt to autosave before exiting
+			tryAutoSaving();
+			break;
+		default:
+			break;
 		}
 	}
 
diff --git a/engines/mohawk/myst.h b/engines/mohawk/myst.h
index 22e6982..6367072 100644
--- a/engines/mohawk/myst.h
+++ b/engines/mohawk/myst.h
@@ -193,6 +193,7 @@ public:
 	Common::Error saveGameState(int slot, const Common::String &desc) override;
 	void tryAutoSaving();
 	bool hasFeature(EngineFeature f) const override;
+	static Common::Array<Common::Keymap *> initKeymaps(const char *target);
 
 	void resumeFromMainMenu();
 


Commit: 43184657e9526bd2ea1b54f6eed9f93622ec15f4
    https://github.com/scummvm/scummvm/commit/43184657e9526bd2ea1b54f6eed9f93622ec15f4
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:30+01:00

Commit Message:
EVENTS: Disable ScummVM's source of keyboard repeat events by default

Backends can still (and do) generate such events. This works around an
issue with the keymapper where the "DOWN" event would be mapped to a
key, but the corresponding "UP" event would be mapped to another one due
to a keymap change. The keyboard repeat generation system would believe
the key to be still pressed and send a continuous stream of repeat
events.
Ideally the keymapper should be fixed to always generate matching event
pairs. However this source of an infinite stream of events still looks
like trouble waiting to happen to me. Hence disabling it by default.

Changed paths:
    backends/events/default/default-events.cpp
    backends/platform/sdl/sdl.cpp


diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp
index c0ceedb..413d428 100644
--- a/backends/events/default/default-events.cpp
+++ b/backends/events/default/default-events.cpp
@@ -42,7 +42,7 @@ DefaultEventManager::DefaultEventManager(Common::EventSource *boss) :
 	_shouldQuit(false),
 	_shouldRTL(false),
 	_confirmExitDialogActive(false),
-	_shouldGenerateKeyRepeatEvents(true) {
+	_shouldGenerateKeyRepeatEvents(false) {
 
 	assert(boss);
 
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 8af126f..faa3234 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -207,9 +207,9 @@ void OSystem_SDL::initBackend() {
 
 	if (_eventManager == nullptr) {
 		DefaultEventManager *eventManager = new DefaultEventManager(_eventSource);
-#if SDL_VERSION_ATLEAST(2, 0, 0)
-		// SDL 2 generates its own keyboard repeat events.
-		eventManager->setGenerateKeyRepeatEvents(false);
+#if !SDL_VERSION_ATLEAST(2, 0, 0)
+		// SDL 1 does not generate its own keyboard repeat events.
+		eventManager->setGenerateKeyRepeatEvents(true);
 #endif
 		_eventManager = eventManager;
 	}


Commit: 2ef73654013b55a49e54390f80caa07c6b0e97b2
    https://github.com/scummvm/scummvm/commit/2ef73654013b55a49e54390f80caa07c6b0e97b2
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:30+01:00

Commit Message:
KEYMAPPER: Change backend default bindings to replace keymap defaults

Previously backend defaults where added to the keymap defaults.
However, it became apparent backends need to change the default bindings
to resolve conflicts.

Changed paths:
    backends/keymapper/keymap.cpp
    backends/keymapper/keymap.h
    backends/keymapper/keymapper-defaults.h
    backends/keymapper/keymapper.cpp
    backends/keymapper/keymapper.h
    backends/platform/maemo/maemo.cpp
    backends/platform/maemo/maemo.h
    base/main.cpp


diff --git a/backends/keymapper/keymap.cpp b/backends/keymapper/keymap.cpp
index 8dd795a..e161439 100644
--- a/backends/keymapper/keymap.cpp
+++ b/backends/keymapper/keymap.cpp
@@ -84,7 +84,7 @@ void Keymap::unregisterMapping(Action *action) {
 void Keymap::resetMapping(Action *action) {
 	unregisterMapping(action);
 
-	const Array<String> &hwInputIds = action->getDefaultInputMapping();
+	StringArray hwInputIds = getActionDefaultMappings(action);
 	registerMappings(action, hwInputIds);
 }
 
@@ -168,28 +168,33 @@ void Keymap::setHardwareInputs(HardwareInputSet *hardwareInputSet) {
 	_hardwareInputSet = hardwareInputSet;
 }
 
-void Keymap::setBackendDefaultBindings(const Common::KeymapperDefaultBindings *backendDefaultBindings) {
+void Keymap::setBackendDefaultBindings(const KeymapperDefaultBindings *backendDefaultBindings) {
 	_backendDefaultBindings = backendDefaultBindings;
 }
 
-void Keymap::registerBackendDefaultMappings() {
-	assert(_backendDefaultBindings);
-
-	for (ActionArray::const_iterator it = _actions.begin(); it != _actions.end(); ++it) {
-		Action *action = *it;
-		Common::String defaultHwId = _backendDefaultBindings->getDefaultBinding(_id, action->id);
-
-		if (!defaultHwId.empty()) {
-			action->addDefaultInputMapping(defaultHwId);
-			continue;
+StringArray Keymap::getActionDefaultMappings(Action *action) {
+	// Backend default mappings overrides keymap default mappings, so backends can resolve mapping conflicts.
+	// Empty mappings are valid and mean the action should not be mapped by default.
+	if (_backendDefaultBindings) {
+		KeymapperDefaultBindings::const_iterator it = _backendDefaultBindings->findDefaultBinding(_id, action->id);
+		if (it != _backendDefaultBindings->end()) {
+			if (it->_value.empty()) {
+				return StringArray();
+			}
+			return StringArray(1, it->_value);
 		}
 
 		// If no keymap-specific default mapping was found, look for a standard action binding
-		defaultHwId = _backendDefaultBindings->getDefaultBinding(kStandardActionsKeymapName, action->id);
-		if (!defaultHwId.empty()) {
-			action->addDefaultInputMapping(defaultHwId);
+		it = _backendDefaultBindings->findDefaultBinding(kStandardActionsKeymapName, action->id);
+		if (it != _backendDefaultBindings->end()) {
+			if (it->_value.empty()) {
+				return StringArray();
+			}
+			return StringArray(1, it->_value);
 		}
 	}
+
+	return action->getDefaultInputMapping();
 }
 
 void Keymap::loadMappings() {
@@ -200,10 +205,6 @@ void Keymap::loadMappings() {
 		return;
 	}
 
-	if (_backendDefaultBindings) {
-		registerBackendDefaultMappings();
-	}
-
 	String prefix = KEYMAP_KEY_PREFIX + _id + "_";
 
 	_hwActionMap.clear();
@@ -211,29 +212,28 @@ void Keymap::loadMappings() {
 		Action *action = *it;
 		String confKey = prefix + action->id;
 
-		Array<String> hwInputIds;
+		StringArray hwInputIds;
 		if (_configDomain->contains(confKey)) {
 			// The configuration value is a list of space separated hardware input ids
 			StringTokenizer hwInputTokenizer = _configDomain->getVal(confKey);
 
-			String hwInputId;
-			while ((hwInputId = hwInputTokenizer.nextToken()) != "") {
-				hwInputIds.push_back(hwInputId);
+			while (!hwInputTokenizer.empty()) {
+				hwInputIds.push_back(hwInputTokenizer.nextToken());
 			}
 		} else {
 			// If the configuration key was not found, use the default mapping
-			hwInputIds = action->getDefaultInputMapping();
+			hwInputIds = getActionDefaultMappings(action);
 		}
 
 		registerMappings(action, hwInputIds);
 	}
 }
 
-void Keymap::registerMappings(Action *action, const Array <String> &hwInputIds) {
+void Keymap::registerMappings(Action *action, const StringArray &hwInputIds) {
 	assert(_hardwareInputSet);
 
 	for (uint i = 0; i < hwInputIds.size(); i++) {
-			HardwareInput hwInput = _hardwareInputSet->findHardwareInput(hwInputIds[i].c_str());
+			HardwareInput hwInput = _hardwareInputSet->findHardwareInput(hwInputIds[i]);
 
 			if (hwInput.type == kHardwareInputTypeInvalid) {
 				// Silently ignore unknown hardware ids because the current device may not have inputs matching the defaults
@@ -256,7 +256,7 @@ void Keymap::saveMappings() {
 		Action *action = *it;
 		Array<HardwareInput> mappedInputs = getActionMapping(action);
 
-		if (areMappingsIdentical(mappedInputs, action->getDefaultInputMapping())) {
+		if (areMappingsIdentical(mappedInputs, getActionDefaultMappings(action))) {
 			// If the current mapping is the default, don't write anything to the config manager
 			_configDomain->erase(prefix + action->id);
 			continue;
@@ -276,24 +276,24 @@ void Keymap::saveMappings() {
 	}
 }
 
-bool Keymap::areMappingsIdentical(const Array<HardwareInput> &inputs, const StringArray &mapping) {
-	if (inputs.size() != mapping.size()) {
-		return false;
-	}
-
+bool Keymap::areMappingsIdentical(const Array<HardwareInput> &mappingsA, const StringArray &mappingsB) {
 	// Assumes array values are not duplicated, but registerMapping and addDefaultInputMapping ensure that
 
 	uint foundCount = 0;
-	for (uint i = 0; i < inputs.size(); i++) {
-		for (uint j = 0; j < mapping.size(); j++) {
-			if (inputs[i].id == mapping[j]) {
+	for (uint i = 0; i < mappingsB.size(); i++) {
+		// We resolve the hardware input to make sure it is not a default for some hardware we don't have currently
+		HardwareInput mappingB = _hardwareInputSet->findHardwareInput(mappingsB[i]);
+		if (mappingB.type == kHardwareInputTypeInvalid) continue;
+
+		for (uint j = 0; j < mappingsA.size(); j++) {
+			if (mappingsA[j].id == mappingB.id) {
 				foundCount++;
 				break;
 			}
 		}
 	}
 
-	return foundCount == inputs.size();
+	return foundCount == mappingsA.size();
 }
 
 } // End of namespace Common
diff --git a/backends/keymapper/keymap.h b/backends/keymapper/keymap.h
index d81cfd4..4d584a2 100644
--- a/backends/keymapper/keymap.h
+++ b/backends/keymapper/keymap.h
@@ -127,6 +127,14 @@ public:
 	const ActionArray &getActions() const { return _actions; }
 
 	/**
+	 * Get the default input mappings for an action.
+	 *
+	 * Backend-specific mappings replace the default mappings
+	 * specified when creating the keymap.
+	 */
+	StringArray getActionDefaultMappings(Action *action);
+
+	/**
 	 * Load this keymap's mappings from the config manager.
 	 * @param hwInputs	the set to retrieve hardware input pointers from
 	 */
@@ -175,8 +183,6 @@ private:
 	ConfigManager::Domain *_configDomain;
 	HardwareInputSet *_hardwareInputSet;
 	const KeymapperDefaultBindings *_backendDefaultBindings;
-
-	void registerBackendDefaultMappings();
 };
 
 typedef Array<Keymap *> KeymapArray;
diff --git a/backends/keymapper/keymapper-defaults.h b/backends/keymapper/keymapper-defaults.h
index b6d395e..e0395bf 100644
--- a/backends/keymapper/keymapper-defaults.h
+++ b/backends/keymapper/keymapper-defaults.h
@@ -30,7 +30,7 @@
 
 namespace Common {
 
-class KeymapperDefaultBindings : HashMap<String, String> {
+class KeymapperDefaultBindings : public HashMap<String, String> {
 public:
 	/**
 	 * This sets a default hwInput for a given Keymap Action
@@ -45,7 +45,9 @@ public:
 	 * @param actionId String representing Action id (Action.id)
 	 * @return String representing the HardwareInput id (HardwareInput.id)
 	 */
-	String getDefaultBinding(String keymapId, String actionId) const { return getVal(keymapId + "_" + actionId); }
+	const_iterator findDefaultBinding(String keymapId, String actionId) const {
+		return find(keymapId + "_" + actionId);
+	}
 };
 
 } //namespace Common
diff --git a/backends/keymapper/keymapper.cpp b/backends/keymapper/keymapper.cpp
index 649db85..e7d8761 100644
--- a/backends/keymapper/keymapper.cpp
+++ b/backends/keymapper/keymapper.cpp
@@ -24,6 +24,7 @@
 
 #include "backends/keymapper/action.h"
 #include "backends/keymapper/hardware-input.h"
+#include "backends/keymapper/keymapper-defaults.h"
 
 #include "common/system.h"
 
@@ -35,19 +36,20 @@ static const uint32 kDelayMouseEventMillis = 50;
 
 Keymapper::Keymapper(EventManager *eventMan) :
 		_eventMan(eventMan),
-		_enabled(true),
-		_enabledKeymapType(Keymap::kKeymapTypeGlobal),
 		_hardwareInputs(nullptr),
 		_backendDefaultBindings(nullptr),
-		_delayedEventSource(new DelayedEventSource()) {
+		_delayedEventSource(new DelayedEventSource()),
+		_enabled(true),
+		_enabledKeymapType(Keymap::kKeymapTypeGlobal) {
 	_eventMan->getEventDispatcher()->registerSource(_delayedEventSource, true);
 }
 
 Keymapper::~Keymapper() {
-	delete _hardwareInputs;
 	for (KeymapArray::iterator it = _keymaps.begin(); it != _keymaps.end(); it++) {
 		delete *it;
 	}
+	delete _backendDefaultBindings;
+	delete _hardwareInputs;
 }
 
 void Keymapper::registerHardwareInputSet(HardwareInputSet *inputs) {
@@ -65,7 +67,7 @@ void Keymapper::registerHardwareInputSet(HardwareInputSet *inputs) {
 	_hardwareInputs = inputs;
 }
 
-void Keymapper::registerBackendDefaultBindings(const Common::KeymapperDefaultBindings *backendDefaultBindings) {
+void Keymapper::registerBackendDefaultBindings(KeymapperDefaultBindings *backendDefaultBindings) {
 	if (!_keymaps.empty())
 		error("Backend default bindings must be defined before adding keymaps");
 
diff --git a/backends/keymapper/keymapper.h b/backends/keymapper/keymapper.h
index 3c0317e..4adee53 100644
--- a/backends/keymapper/keymapper.h
+++ b/backends/keymapper/keymapper.h
@@ -54,13 +54,17 @@ public:
 	/**
 	 * Registers a HardwareInputSet with the Keymapper
 	 * @note should only be called once (during backend initialisation)
+	 *
+	 * Transfers ownership to the Keymapper
 	 */
 	void registerHardwareInputSet(HardwareInputSet *inputs);
 
 	/**
 	 * Registers platform-specific default mappings for keymap actions
+	 *
+	 * Transfers ownership to the Keymapper
 	 */
-	void registerBackendDefaultBindings(const KeymapperDefaultBindings *backendDefaultBindings);
+	void registerBackendDefaultBindings(KeymapperDefaultBindings *backendDefaultBindings);
 
 	/**
 	 * Add a keymap to the global domain.
@@ -126,7 +130,7 @@ public:
 private:
 	EventManager *_eventMan;
 	HardwareInputSet *_hardwareInputs;
-	const KeymapperDefaultBindings *_backendDefaultBindings;
+	KeymapperDefaultBindings *_backendDefaultBindings;
 	DelayedEventSource *_delayedEventSource;
 
 	enum IncomingEventType {
diff --git a/backends/platform/maemo/maemo.cpp b/backends/platform/maemo/maemo.cpp
index 4b1ee9e..9231c7d 100644
--- a/backends/platform/maemo/maemo.cpp
+++ b/backends/platform/maemo/maemo.cpp
@@ -45,35 +45,6 @@ OSystem_SDL_Maemo::OSystem_SDL_Maemo()
 
 OSystem_SDL_Maemo::~OSystem_SDL_Maemo() {
 	delete _eventObserver;
-	delete _keymapperDefaultBindings;
-}
-
-static void registerDefaultKeyBindings(Common::KeymapperDefaultBindings *_keymapperDefaultBindings, Model _model) {
-	_keymapperDefaultBindings->setDefaultBinding("gui", "REMP", "HOME");
-	_keymapperDefaultBindings->setDefaultBinding("global", "REMP", "HOME");
-
-	if (_model.hasMenuKey && _model.hasHwKeyboard) {
-		_keymapperDefaultBindings->setDefaultBinding("gui", "FULS", "FULLSCREEN");
-		_keymapperDefaultBindings->setDefaultBinding("global", "FULS", "FULLSCREEN");
-	}
-
-	if (_model.hasHwKeyboard) {
-		_keymapperDefaultBindings->setDefaultBinding("gui", "VIRT", "C+ZOOMMINUS");
-		_keymapperDefaultBindings->setDefaultBinding("global", "VIRT", "C+ZOOMMINUS");
-	} else {
-		_keymapperDefaultBindings->setDefaultBinding("gui", "VIRT", "FULLSCREEN");
-		_keymapperDefaultBindings->setDefaultBinding("global", "VIRT", "FULLSCREEN");
-	}
-
-	if (_model.hasMenuKey )
-		_keymapperDefaultBindings->setDefaultBinding("global", "MENU", "MENU");
-	else
-		_keymapperDefaultBindings->setDefaultBinding("global", "MENU", "S+C+M");
-
-	_keymapperDefaultBindings->setDefaultBinding("gui", "CLOS", "ESCAPE");
-
-	_keymapperDefaultBindings->setDefaultBinding("maemo", "RCLK", "ZOOMPLUS");
-	_keymapperDefaultBindings->setDefaultBinding("maemo", "CLKM", "ZOOMMINUS");
 }
 
 void OSystem_SDL_Maemo::init() {
@@ -99,13 +70,8 @@ void OSystem_SDL_Maemo::initBackend() {
 	if (_eventObserver == 0)
 		_eventObserver = new MaemoSdlEventObserver((MaemoSdlEventSource *)_eventSource);
 
-	if (_keymapperDefaultBindings == 0)
-		_keymapperDefaultBindings = new Common::KeymapperDefaultBindings();
-
 	_model = detectModel();
 
-	registerDefaultKeyBindings(_keymapperDefaultBindings, _model);
-
 	// Call parent implementation of this method
 	OSystem_POSIX::initBackend();
 	initObserver();
@@ -221,6 +187,38 @@ Common::KeymapArray OSystem_SDL_Maemo::getGlobalKeymaps() {
 	return globalMaps;
 }
 
+Common::KeymapperDefaultBindings *OSystem_SDL_Maemo::getKeymapperDefaultBindings() {
+	Common::KeymapperDefaultBindings *keymapperDefaultBindings = new Common::KeymapperDefaultBindings();
+
+	keymapperDefaultBindings->setDefaultBinding("gui", "REMP", "HOME");
+	keymapperDefaultBindings->setDefaultBinding("global", "REMP", "HOME");
+
+	if (_model.hasMenuKey && _model.hasHwKeyboard) {
+		keymapperDefaultBindings->setDefaultBinding("gui", "FULS", "FULLSCREEN");
+		keymapperDefaultBindings->setDefaultBinding("global", "FULS", "FULLSCREEN");
+	}
+
+	if (_model.hasHwKeyboard) {
+		keymapperDefaultBindings->setDefaultBinding("gui", "VIRT", "C+ZOOMMINUS");
+		keymapperDefaultBindings->setDefaultBinding("global", "VIRT", "C+ZOOMMINUS");
+	} else {
+		keymapperDefaultBindings->setDefaultBinding("gui", "VIRT", "FULLSCREEN");
+		keymapperDefaultBindings->setDefaultBinding("global", "VIRT", "FULLSCREEN");
+	}
+
+	if (_model.hasMenuKey )
+		keymapperDefaultBindings->setDefaultBinding("global", "MENU", "MENU");
+	else
+		keymapperDefaultBindings->setDefaultBinding("global", "MENU", "S+C+M");
+
+	keymapperDefaultBindings->setDefaultBinding("gui", "CLOS", "ESCAPE");
+
+	keymapperDefaultBindings->setDefaultBinding("maemo", "RCLK", "ZOOMPLUS");
+	keymapperDefaultBindings->setDefaultBinding("maemo", "CLKM", "ZOOMMINUS");
+
+	return keymapperDefaultBindings;
+}
+
 void OSystem_SDL_Maemo::initObserver() {
 	assert(_eventManager);
 	_eventManager->getEventDispatcher()->registerObserver(_eventObserver, 10, false);
diff --git a/backends/platform/maemo/maemo.h b/backends/platform/maemo/maemo.h
index b565a68..91ca084 100644
--- a/backends/platform/maemo/maemo.h
+++ b/backends/platform/maemo/maemo.h
@@ -43,7 +43,7 @@ public:
 	virtual void setWindowCaption(const char *caption);
 	virtual Common::HardwareInputSet *getHardwareInputSet();
 	Common::KeymapArray getGlobalKeymaps() override;
-	virtual Common::KeymapperDefaultBindings *getKeymapperDefaultBindings() { return _keymapperDefaultBindings; }
+	Common::KeymapperDefaultBindings *getKeymapperDefaultBindings() override;
 
 	Model getModel() { return _model; }
 
@@ -54,7 +54,6 @@ private:
 	const Model detectModel();
 	Model _model;
 	MaemoSdlEventObserver *_eventObserver;
-	Common::KeymapperDefaultBindings *_keymapperDefaultBindings;
 };
 
 } // namespace Maemo
diff --git a/base/main.cpp b/base/main.cpp
index d149ed5..8a4d73a 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -361,7 +361,7 @@ static void setupKeymapper(OSystem &system) {
 
 	// Query the backend for hardware keys and default bindings and register them
 	HardwareInputSet *inputSet = system.getHardwareInputSet();
-	const KeymapperDefaultBindings *backendDefaultBindings = system.getKeymapperDefaultBindings();
+	KeymapperDefaultBindings *backendDefaultBindings = system.getKeymapperDefaultBindings();
 
 	mapper->registerHardwareInputSet(inputSet);
 	mapper->registerBackendDefaultBindings(backendDefaultBindings);


Commit: 78ab5715191e9cf7807ce42dba1cf167a862edd1
    https://github.com/scummvm/scummvm/commit/78ab5715191e9cf7807ce42dba1cf167a862edd1
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:30+01:00

Commit Message:
3DS: Update the port to take advantage of the new keymapper

Changed paths:
    backends/platform/3ds/README.md
    backends/platform/3ds/osystem-events.cpp
    backends/platform/3ds/osystem.cpp
    backends/platform/3ds/osystem.h


diff --git a/backends/platform/3ds/README.md b/backends/platform/3ds/README.md
index fb30b9f..834976a 100644
--- a/backends/platform/3ds/README.md
+++ b/backends/platform/3ds/README.md
@@ -54,18 +54,23 @@ the `scummvm.cia` file.
 
 2.1) Default key mappings
 -------------------------
-The D-Pad and A/B/X/Y buttons have mirrored usage. So they do the same things
-depending on if you're right or left-handed.
+
+The key mappings can be customized in the options dialog for the global mappings,
+and in the edit game dialog for per-game mappings. Per-game mappings overlay the
+global mappings, so if a button is bound to an action twice, the per-game mapping
+wins.
+
+The default keymap is:
 
 |  Buttons   |   Function                     |
 |------------|--------------------------------|
-| A / D-left | Left-click                     |
-| X / D-up   | Right-click                    |
-| B / D-down | ESC (skips cutscenes and such) |
-| Y / D-right| Use virtual keyboard           |
+| A          | Left-click                     |
+| B          | Right-click                    |
+| Y          | ESC (skips cutscenes and such) |
+| X          | Use virtual keyboard           |
 | L          | Toggle magnify mode on/off     |
 | R          | Toggle hover/drag modes        |
-| Start      | Open game menu                 |
+| Start      | Open global main menu          |
 | Select     | Open 3DS config menu           |
 | Circle Pad | Move the cursor                |
 
diff --git a/backends/platform/3ds/osystem-events.cpp b/backends/platform/3ds/osystem-events.cpp
index 6af7c4d..2285933 100644
--- a/backends/platform/3ds/osystem-events.cpp
+++ b/backends/platform/3ds/osystem-events.cpp
@@ -24,6 +24,12 @@
 
 #include "backends/platform/3ds/osystem.h"
 
+#include "backends/keymapper/action.h"
+#include "backends/keymapper/keymapper-defaults.h"
+#include "backends/keymapper/hardware-input.h"
+#include "backends/keymapper/keymap.h"
+#include "backends/keymapper/keymapper.h"
+#include "backends/keymapper/standard-actions.h"
 #include "backends/platform/3ds/config.h"
 #include "backends/platform/3ds/options-dialog.h"
 #include "backends/timer/default/default-timer.h"
@@ -37,20 +43,51 @@ static Common::Mutex *eventMutex;
 static InputMode inputMode = MODE_DRAG;
 static InputMode savedInputMode = MODE_DRAG;
 static aptHookCookie cookie;
-static bool optionMenuOpening = false;
+
+const Common::HardwareInputTableEntry ctrJoystickButtons[] = {
+    { "JOY_A",              Common::JOYSTICK_BUTTON_A,              _s("A")           },
+    { "JOY_B",              Common::JOYSTICK_BUTTON_B,              _s("B")           },
+    { "JOY_X",              Common::JOYSTICK_BUTTON_X,              _s("X")           },
+    { "JOY_Y",              Common::JOYSTICK_BUTTON_Y,              _s("Y")           },
+    { "JOY_BACK",           Common::JOYSTICK_BUTTON_BACK,           _s("Select")      },
+    { "JOY_START",          Common::JOYSTICK_BUTTON_START,          _s("Start")       },
+    { "JOY_LEFT_STICK",     Common::JOYSTICK_BUTTON_LEFT_STICK,     _s("ZL")          },
+    { "JOY_RIGHT_STICK",    Common::JOYSTICK_BUTTON_RIGHT_STICK,    _s("ZR")          },
+    { "JOY_LEFT_SHOULDER",  Common::JOYSTICK_BUTTON_LEFT_SHOULDER,  _s("L")           },
+    { "JOY_RIGHT_SHOULDER", Common::JOYSTICK_BUTTON_RIGHT_SHOULDER, _s("R")           },
+    { "JOY_UP",             Common::JOYSTICK_BUTTON_DPAD_UP,        _s("D-pad Up")    },
+    { "JOY_DOWN",           Common::JOYSTICK_BUTTON_DPAD_DOWN,      _s("D-pad Down")  },
+    { "JOY_LEFT",           Common::JOYSTICK_BUTTON_DPAD_LEFT,      _s("D-pad Left")  },
+    { "JOY_RIGHT",          Common::JOYSTICK_BUTTON_DPAD_RIGHT,     _s("D-pad Right") },
+    { nullptr,              0,                                      nullptr           }
+};
+
+const Common::HardwareInputTableEntry ctrMouseButtons[] = {
+    { "MOUSE_LEFT",   Common::MOUSE_BUTTON_LEFT,   _s("Touch") },
+    { nullptr,        0,                           nullptr     }
+};
 
 static void pushEventQueue(Common::Queue<Common::Event> *queue, Common::Event &event) {
 	Common::StackLock lock(*eventMutex);
 	queue->push(event);
 }
 
+static void doJoyEvent(Common::Queue<Common::Event> *queue, u32 keysPressed, u32 keysReleased, u32 ctrKey, uint8 svmButton) {
+	if (keysPressed & ctrKey || keysReleased & ctrKey) {
+		Common::Event event;
+		event.type = (keysPressed & ctrKey) ? Common::EVENT_JOYBUTTON_DOWN : Common::EVENT_JOYBUTTON_UP;
+		event.joystick.button = svmButton;
+
+		pushEventQueue(queue, event);
+	}
+}
+
 static void eventThreadFunc(void *arg) {
 	OSystem_3DS *osys = (OSystem_3DS *)g_system;
 	auto eventQueue = (Common::Queue<Common::Event> *)arg;
 
 	uint32 touchStartTime = osys->getMillis();
 	touchPosition lastTouch = {0, 0};
-	bool isRightClick = false;
 	float cursorDeltaX = 0;
 	float cursorDeltaY = 0;
 	int circleDeadzone = 20;
@@ -100,9 +137,8 @@ static void eventThreadFunc(void *arg) {
 
 			if (keysPressed & KEY_TOUCH) {
 				touchStartTime = osys->getMillis();
-				isRightClick = (held & KEY_X || held & KEY_DUP);
 				if (inputMode == MODE_DRAG) {
-					event.type = isRightClick ? Common::EVENT_RBUTTONDOWN : Common::EVENT_LBUTTONDOWN;
+					event.type = Common::EVENT_LBUTTONDOWN;
 					pushEventQueue(eventQueue, event);
 				}
 			} else if (touch.px != lastTouch.px || touch.py != lastTouch.py) {
@@ -115,15 +151,15 @@ static void eventThreadFunc(void *arg) {
 			event.mouse.x = lastTouch.px;
 			event.mouse.y = lastTouch.py;
 			if (inputMode == MODE_DRAG) {
-				event.type = isRightClick ? Common::EVENT_RBUTTONUP : Common::EVENT_LBUTTONUP;
+				event.type = Common::EVENT_LBUTTONUP;
 				pushEventQueue(eventQueue, event);
 			} else if (osys->getMillis() - touchStartTime < 200) {
 				// Process click in MODE_HOVER
 				event.type = Common::EVENT_MOUSEMOVE;
 				pushEventQueue(eventQueue, event);
-				event.type = isRightClick ? Common::EVENT_RBUTTONDOWN : Common::EVENT_LBUTTONDOWN;
+				event.type = Common::EVENT_LBUTTONDOWN;
 				pushEventQueue(eventQueue, event);
-				event.type = isRightClick ? Common::EVENT_RBUTTONUP : Common::EVENT_LBUTTONUP;
+				event.type = Common::EVENT_LBUTTONUP;
 				pushEventQueue(eventQueue, event);
 			}
 		} else if (cursorDeltaX != 0 || cursorDeltaY != 0) {
@@ -142,105 +178,20 @@ static void eventThreadFunc(void *arg) {
 		}
 
 		// Button events
-		if (keysPressed & KEY_L) {
-			if (g_gui.isActive()) {
-				osys->displayMessageOnOSD(_("Magnify Mode cannot be activated in menus."));
-			} else if (config.screen != kScreenBoth && osys->getMagnifyMode() == MODE_MAGOFF) {
-				// TODO: Automatically enable both screens while magnify mode is on
-				osys->displayMessageOnOSD(_("Magnify Mode can only be activated\n when both screens are enabled."));
-			} else if (osys->getWidth() <= 400 && osys->getHeight() <= 240) {
-				osys->displayMessageOnOSD(_("In-game resolution too small to magnify."));
-			} else {
-				if (osys->getMagnifyMode() == MODE_MAGOFF) {
-					osys->setMagnifyMode(MODE_MAGON);
-					if (inputMode == MODE_DRAG) {
-						inputMode = MODE_HOVER;
-						osys->displayMessageOnOSD(_("Magnify Mode On. Switching to Hover Mode..."));
-					} else {
-						osys->displayMessageOnOSD(_("Magnify Mode On"));
-					}
-				} else {
-					osys->setMagnifyMode(MODE_MAGOFF);
-					osys->updateSize();
-					if (savedInputMode == MODE_DRAG) {
-						inputMode = savedInputMode;
-						osys->displayMessageOnOSD(_("Magnify Mode Off. Reactivating Drag Mode..."));
-					} else {
-						osys->displayMessageOnOSD(_("Magnify Mode Off"));
-					}
-				}
-			}
-		}
-		if (keysPressed & KEY_R) {
-			if (inputMode == MODE_DRAG) {
-				inputMode = savedInputMode = MODE_HOVER;
-				osys->displayMessageOnOSD(_("Hover Mode"));
-			} else {
-				if (osys->getMagnifyMode() == MODE_MAGOFF) {
-					inputMode = savedInputMode = MODE_DRAG;
-					osys->displayMessageOnOSD(_("Drag Mode"));
-				} else
-					osys->displayMessageOnOSD(_("Cannot Switch to Drag Mode while Magnify Mode is On"));
-			}
-		}
-		if (keysPressed & KEY_A || keysPressed & KEY_DLEFT || keysReleased & KEY_A || keysReleased & KEY_DLEFT) {
-			// SIMULATE LEFT CLICK
-			event.mouse.x = lastTouch.px;
-			event.mouse.y = lastTouch.py;
-			if (keysPressed & KEY_A || keysPressed & KEY_DLEFT)
-				event.type = Common::EVENT_LBUTTONDOWN;
-			else
-				event.type = Common::EVENT_LBUTTONUP;
-			pushEventQueue(eventQueue, event);
-		}
-		if (keysPressed & KEY_B || keysReleased & KEY_B || keysPressed & KEY_DDOWN || keysReleased & KEY_DDOWN) {
-			if (keysPressed & KEY_B || keysPressed & KEY_DDOWN)
-				event.type = Common::EVENT_KEYDOWN;
-			else
-				event.type = Common::EVENT_KEYUP;
-			event.kbd.keycode = Common::KEYCODE_ESCAPE;
-			event.kbd.ascii = Common::ASCII_ESCAPE;
-			event.kbd.flags = 0;
-			pushEventQueue(eventQueue, event);
-		}
-		if (keysPressed & KEY_X || keysPressed & KEY_DUP || keysReleased & KEY_X || keysReleased & KEY_DUP) {
-			// SIMULATE RIGHT CLICK
-			event.mouse.x = lastTouch.px;
-			event.mouse.y = lastTouch.py;
-			if (keysPressed & KEY_X || keysPressed & KEY_DUP)
-				event.type = Common::EVENT_RBUTTONDOWN;
-			else
-				event.type = Common::EVENT_RBUTTONUP;
-			pushEventQueue(eventQueue, event);
-		}
-		if (keysPressed & KEY_Y || keysPressed & KEY_DRIGHT) {
-			event.type = Common::EVENT_VIRTUAL_KEYBOARD;
-			pushEventQueue(eventQueue, event);
-		}
-		if (keysPressed & KEY_START) {
-			event.type = Common::EVENT_MAINMENU;
-			pushEventQueue(eventQueue, event);
-		}
-		if (keysPressed & KEY_SELECT) {
-			if (!optionMenuOpened)
-				optionMenuOpening = true;
-		}
-
-		// If magnify mode is on when returning to Launcher, turn it off
-		if (g_system->getEventManager()->shouldRTL()) {
-			if (osys->getMagnifyMode() == MODE_MAGON) {
-				osys->setMagnifyMode(MODE_MAGOFF);
-				osys->updateSize();
-				if (savedInputMode == MODE_DRAG) {
-					inputMode = savedInputMode;
-					osys->displayMessageOnOSD(_("Magnify Mode Off. Reactivating Drag Mode.\nReturning to Launcher..."));
-				} else
-					osys->displayMessageOnOSD(_("Magnify Mode Off. Returning to Launcher..."));
-			}
-		}
-
-		// TODO: EVENT_PREDICTIVE_DIALOG
-		// EVENT_SCREEN_CHANGED
+		doJoyEvent(eventQueue, keysPressed, keysReleased, KEY_L,      Common::JOYSTICK_BUTTON_LEFT_SHOULDER);
+		doJoyEvent(eventQueue, keysPressed, keysReleased, KEY_R,      Common::JOYSTICK_BUTTON_RIGHT_SHOULDER);
+		doJoyEvent(eventQueue, keysPressed, keysReleased, KEY_A,      Common::JOYSTICK_BUTTON_A);
+		doJoyEvent(eventQueue, keysPressed, keysReleased, KEY_B,      Common::JOYSTICK_BUTTON_B);
+		doJoyEvent(eventQueue, keysPressed, keysReleased, KEY_X,      Common::JOYSTICK_BUTTON_X);
+		doJoyEvent(eventQueue, keysPressed, keysReleased, KEY_Y,      Common::JOYSTICK_BUTTON_Y);
+		doJoyEvent(eventQueue, keysPressed, keysReleased, KEY_DUP,    Common::JOYSTICK_BUTTON_DPAD_UP);
+		doJoyEvent(eventQueue, keysPressed, keysReleased, KEY_DDOWN,  Common::JOYSTICK_BUTTON_DPAD_DOWN);
+		doJoyEvent(eventQueue, keysPressed, keysReleased, KEY_DLEFT,  Common::JOYSTICK_BUTTON_DPAD_LEFT);
+		doJoyEvent(eventQueue, keysPressed, keysReleased, KEY_DRIGHT, Common::JOYSTICK_BUTTON_DPAD_RIGHT);
+		doJoyEvent(eventQueue, keysPressed, keysReleased, KEY_START,  Common::JOYSTICK_BUTTON_START);
+		doJoyEvent(eventQueue, keysPressed, keysReleased, KEY_SELECT, Common::JOYSTICK_BUTTON_BACK);
+		doJoyEvent(eventQueue, keysPressed, keysReleased, KEY_ZL,     Common::JOYSTICK_BUTTON_LEFT_STICK);
+		doJoyEvent(eventQueue, keysPressed, keysReleased, KEY_ZR,     Common::JOYSTICK_BUTTON_RIGHT_STICK);
 	}
 }
 
@@ -283,6 +234,17 @@ static void timerThreadFunc(void *arg) {
 	}
 }
 
+Common::HardwareInputSet *OSystem_3DS::getHardwareInputSet() {
+	using namespace Common;
+
+	CompositeHardwareInputSet *inputSet = new CompositeHardwareInputSet();
+	// Touch input sends mouse events for now, so we need to declare we have a mouse...
+	inputSet->addHardwareInputSet(new MouseHardwareInputSet(ctrMouseButtons));
+	inputSet->addHardwareInputSet(new JoystickHardwareInputSet(ctrJoystickButtons));
+
+	return inputSet;
+}
+
 void OSystem_3DS::initEvents() {
 	eventMutex = new Common::Mutex();
 	s32 prio = 0;
@@ -291,9 +253,12 @@ void OSystem_3DS::initEvents() {
 	_eventThread = threadCreate(&eventThreadFunc, &_eventQueue, 32 * 1024, prio - 1, -2, false);
 
 	aptHook(&cookie, aptHookFunc, this);
+	_eventManager->getEventDispatcher()->registerObserver(this, 10, false);
 }
 
 void OSystem_3DS::destroyEvents() {
+	_eventManager->getEventDispatcher()->unregisterObserver(this);
+
 	threadJoin(_timerThread, U64_MAX);
 	threadFree(_timerThread);
 
@@ -321,16 +286,64 @@ void OSystem_3DS::clipPoint(touchPosition &point) {
 	}
 }
 
-void OSystem_3DS::setMagnifyMode(MagnifyMode mode) {
-	_magnifyMode = mode;
+enum _3DSCustomEvent {
+	k3DSEventToggleDragMode,
+	k3DSEventToggleMagnifyMode,
+	k3DSEventOpenSettings
+};
+
+Common::KeymapArray OSystem_3DS::getGlobalKeymaps() {
+	using namespace Common;
+
+	Keymap *keymap = new Keymap(Keymap::kKeymapTypeGlobal, "3ds", "3DS");
+
+	Action *act;
+
+	act = new Action("DRAGM", _("Toggle Drag Mode"));
+	act->setCustomBackendActionEvent(k3DSEventToggleDragMode);
+	act->addDefaultInputMapping("JOY_LEFT_SHOULDER");
+	keymap->addAction(act);
+
+	act = new Action("MAGM", _("Toggle Magnify Mode"));
+	act->setCustomBackendActionEvent(k3DSEventToggleMagnifyMode);
+	act->addDefaultInputMapping("JOY_RIGHT_SHOULDER");
+	keymap->addAction(act);
+
+	act = new Action("OPTS", _("Open 3DS Settings"));
+	act->setCustomBackendActionEvent(k3DSEventOpenSettings);
+	act->addDefaultInputMapping("JOY_SELECT");
+	keymap->addAction(act);
+
+	return Keymap::arrayOf(keymap);
+}
+
+Common::KeymapperDefaultBindings *OSystem_3DS::getKeymapperDefaultBindings() {
+	Common::KeymapperDefaultBindings *keymapperDefaultBindings = new Common::KeymapperDefaultBindings();
+
+	// Bind the virtual keyboard to X so SELECT can be used for the 3DS options dialog
+	keymapperDefaultBindings->setDefaultBinding(Common::kGlobalKeymapName, "VIRT", "JOY_X");
+
+	// Unmap the main menu standard action so LEFT_SHOULDER can be used for drag mode
+	keymapperDefaultBindings->setDefaultBinding("engine-default", Common::kStandardActionOpenMainMenu, "");
+
+	return keymapperDefaultBindings;
 }
 
 bool OSystem_3DS::pollEvent(Common::Event &event) {
 	aptMainLoop(); // Call apt hook when necessary
 
-	if (optionMenuOpening) {
-		optionMenuOpening = false;
-		runOptionsDialog();
+	// If magnify mode is on when returning to Launcher, turn it off
+	if (_eventManager->shouldRTL()) {
+		if (_magnifyMode == MODE_MAGON) {
+			_magnifyMode = MODE_MAGOFF;
+			updateSize();
+			if (savedInputMode == MODE_DRAG) {
+				inputMode = savedInputMode;
+				displayMessageOnOSD(_("Magnify Mode Off. Reactivating Drag Mode.\nReturning to Launcher..."));
+			} else {
+				displayMessageOnOSD(_("Magnify Mode Off. Returning to Launcher..."));
+			}
+		}
 	}
 
 	Common::StackLock lock(*eventMutex);
@@ -342,7 +355,79 @@ bool OSystem_3DS::pollEvent(Common::Event &event) {
 	return true;
 }
 
+bool OSystem_3DS::notifyEvent(const Common::Event &event) {
+	if (event.type != Common::EVENT_CUSTOM_BACKEND_ACTION_START
+	        && event.type != Common::EVENT_CUSTOM_BACKEND_ACTION_END) {
+		return false; // We're only interested in custom backend events
+	}
+
+	if (event.type == Common::EVENT_CUSTOM_BACKEND_ACTION_END) {
+		return true; // We'll say we have handled the event so it is not propagated
+	}
+
+	switch ((_3DSCustomEvent)event.customType) {
+	case k3DSEventToggleDragMode:
+		if (inputMode == MODE_DRAG) {
+			inputMode = savedInputMode = MODE_HOVER;
+			displayMessageOnOSD(_("Hover Mode"));
+		} else {
+			if (_magnifyMode == MODE_MAGOFF) {
+				inputMode = savedInputMode = MODE_DRAG;
+				displayMessageOnOSD(_("Drag Mode"));
+			} else {
+				displayMessageOnOSD(_("Cannot Switch to Drag Mode while Magnify Mode is On"));
+			}
+		}
+		return true;
+
+	case k3DSEventToggleMagnifyMode:
+		if (g_gui.isActive()) {
+			displayMessageOnOSD(_("Magnify Mode cannot be activated in menus."));
+		} else if (config.screen != kScreenBoth && _magnifyMode == MODE_MAGOFF) {
+			// TODO: Automatically enable both screens while magnify mode is on
+			displayMessageOnOSD(_("Magnify Mode can only be activated\n when both screens are enabled."));
+		} else if (_gameWidth <= 400 && _gameHeight <= 240) {
+			displayMessageOnOSD(_("In-game resolution too small to magnify."));
+		} else {
+			if (_magnifyMode == MODE_MAGOFF) {
+				_magnifyMode = MODE_MAGON;
+				if (inputMode == MODE_DRAG) {
+					inputMode = MODE_HOVER;
+					displayMessageOnOSD(_("Magnify Mode On. Switching to Hover Mode..."));
+				} else {
+					displayMessageOnOSD(_("Magnify Mode On"));
+				}
+			} else {
+				_magnifyMode = MODE_MAGOFF;
+				updateSize();
+				if (savedInputMode == MODE_DRAG) {
+					inputMode = savedInputMode;
+					displayMessageOnOSD(_("Magnify Mode Off. Reactivating Drag Mode..."));
+				} else {
+					displayMessageOnOSD(_("Magnify Mode Off"));
+				}
+			}
+		}
+		return true;
+
+	case k3DSEventOpenSettings:
+		runOptionsDialog();
+		return true;
+	}
+
+	return false;
+}
+
 void OSystem_3DS::runOptionsDialog() {
+	static bool optionsDialogRunning = false;
+
+	// Prevent opening the options dialog multiple times
+	if (optionsDialogRunning) {
+		return;
+	}
+
+	optionsDialogRunning = true;
+
 	OptionsDialog dialog;
 	if (g_engine)
 		g_engine->pauseEngine(true);
@@ -367,6 +452,8 @@ void OSystem_3DS::runOptionsDialog() {
 			g_gui.checkScreenChange();
 		}
 	}
+
+	optionsDialogRunning = false;
 }
 
 } // namespace _3DS
diff --git a/backends/platform/3ds/osystem.cpp b/backends/platform/3ds/osystem.cpp
index 7ac115b..fc8cf94 100644
--- a/backends/platform/3ds/osystem.cpp
+++ b/backends/platform/3ds/osystem.cpp
@@ -108,6 +108,7 @@ void OSystem_3DS::quit() {
 
 void OSystem_3DS::initBackend() {
 	loadConfig();
+	ConfMan.set("joystick_num", 0);
 	ConfMan.registerDefault("fullscreen", true);
 	ConfMan.registerDefault("aspect_ratio", true);
 	if (!ConfMan.hasKey("vkeybd_pack_name"))
@@ -120,8 +121,8 @@ void OSystem_3DS::initBackend() {
 
 	initGraphics();
 	initAudio();
-	initEvents();
 	EventsBaseBackend::initBackend();
+	initEvents();
 }
 
 void OSystem_3DS::updateConfig() {
diff --git a/backends/platform/3ds/osystem.h b/backends/platform/3ds/osystem.h
index e38579a..2013d10 100644
--- a/backends/platform/3ds/osystem.h
+++ b/backends/platform/3ds/osystem.h
@@ -49,7 +49,7 @@ enum InputMode {
 	MODE_DRAG,
 };
 
-class OSystem_3DS : public EventsBaseBackend, public PaletteManager {
+class OSystem_3DS : public EventsBaseBackend, public PaletteManager, public Common::EventObserver {
 public:
 	OSystem_3DS();
 	virtual ~OSystem_3DS();
@@ -63,7 +63,11 @@ public:
 	virtual void setFeatureState(OSystem::Feature f, bool enable);
 	virtual bool getFeatureState(OSystem::Feature f);
 
-	virtual bool pollEvent(Common::Event &event);
+	bool pollEvent(Common::Event &event) override;
+	bool notifyEvent(const Common::Event &event) override;
+	Common::HardwareInputSet *getHardwareInputSet() override;
+	Common::KeymapArray getGlobalKeymaps() override;
+	Common::KeymapperDefaultBindings *getKeymapperDefaultBindings() override;
 
 	virtual uint32 getMillis(bool skipRecord = false);
 	virtual void delayMillis(uint msecs);
@@ -137,8 +141,6 @@ public:
 	void updateMagnify();
 	void updateConfig();
 	void updateSize();
-	void setMagnifyMode(MagnifyMode mode);
-	MagnifyMode getMagnifyMode(){ return _magnifyMode; }
 
 private:
 	void initGraphics();


Commit: 05a7ca7b7634c162176c4682d3b625fcba2491de
    https://github.com/scummvm/scummvm/commit/05a7ca7b7634c162176c4682d3b625fcba2491de
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:30+01:00

Commit Message:
PS3: Use the appropriate gamepad button names for the keymapper

Changed paths:
    backends/platform/sdl/ps3/ps3.cpp
    backends/platform/sdl/ps3/ps3.h


diff --git a/backends/platform/sdl/ps3/ps3.cpp b/backends/platform/sdl/ps3/ps3.cpp
index 9f77c03..e27ac81 100644
--- a/backends/platform/sdl/ps3/ps3.cpp
+++ b/backends/platform/sdl/ps3/ps3.cpp
@@ -26,15 +26,36 @@
 
 #include "common/scummsys.h"
 #include "common/config-manager.h"
+#include "common/translation.h"
 #include "backends/platform/sdl/ps3/ps3.h"
 #include "backends/graphics/surfacesdl/surfacesdl-graphics.h"
 #include "backends/saves/default/default-saves.h"
 #include "backends/fs/ps3/ps3-fs-factory.h"
 #include "backends/events/ps3sdl/ps3sdl-events.h"
+#include "backends/keymapper/hardware-input.h"
 
 #include <dirent.h>
 #include <sys/stat.h>
 
+static const Common::HardwareInputTableEntry playstationJoystickButtons[] = {
+    { "JOY_A",              Common::JOYSTICK_BUTTON_A,              _s("Cross")       },
+    { "JOY_B",              Common::JOYSTICK_BUTTON_B,              _s("Circle")      },
+    { "JOY_X",              Common::JOYSTICK_BUTTON_X,              _s("Rectangle")   },
+    { "JOY_Y",              Common::JOYSTICK_BUTTON_Y,              _s("Triangle")    },
+    { "JOY_BACK",           Common::JOYSTICK_BUTTON_BACK,           _s("Select")      },
+    { "JOY_GUIDE",          Common::JOYSTICK_BUTTON_GUIDE,          _s("PS")          },
+    { "JOY_START",          Common::JOYSTICK_BUTTON_START,          _s("Start")       },
+    { "JOY_LEFT_STICK",     Common::JOYSTICK_BUTTON_LEFT_STICK,     _s("L3")          },
+    { "JOY_RIGHT_STICK",    Common::JOYSTICK_BUTTON_RIGHT_STICK,    _s("R3")          },
+    { "JOY_LEFT_SHOULDER",  Common::JOYSTICK_BUTTON_LEFT_SHOULDER,  _s("L1")          },
+    { "JOY_RIGHT_SHOULDER", Common::JOYSTICK_BUTTON_RIGHT_SHOULDER, _s("R1")          },
+    { "JOY_UP",             Common::JOYSTICK_BUTTON_DPAD_UP,        _s("D-pad Up")    },
+    { "JOY_DOWN",           Common::JOYSTICK_BUTTON_DPAD_DOWN,      _s("D-pad Down")  },
+    { "JOY_LEFT",           Common::JOYSTICK_BUTTON_DPAD_LEFT,      _s("D-pad Left")  },
+    { "JOY_RIGHT",          Common::JOYSTICK_BUTTON_DPAD_RIGHT,     _s("D-pad Right") },
+    { nullptr,              0,                                      nullptr           }
+};
+
 int access(const char *pathname, int mode) {
 	struct stat sb;
 
@@ -77,3 +98,16 @@ Common::String OSystem_PS3::getDefaultConfigFileName() {
 Common::String OSystem_PS3::getDefaultLogFileName() {
 	return PREFIX "/scummvm.log";
 }
+
+Common::HardwareInputSet *OSystem_PS3::getHardwareInputSet() {
+	using namespace Common;
+
+	CompositeHardwareInputSet *inputSet = new CompositeHardwareInputSet();
+
+	// Users may use USB / bluetooth mice and keyboards
+	inputSet->addHardwareInputSet(new MouseHardwareInputSet(defaultMouseButtons));
+	inputSet->addHardwareInputSet(new KeyboardHardwareInputSet(defaultKeys, defaultModifiers));
+	inputSet->addHardwareInputSet(new JoystickHardwareInputSet(playstationJoystickButtons));
+
+	return inputSet;
+}
diff --git a/backends/platform/sdl/ps3/ps3.h b/backends/platform/sdl/ps3/ps3.h
index 766cf5f..14a8b03 100644
--- a/backends/platform/sdl/ps3/ps3.h
+++ b/backends/platform/sdl/ps3/ps3.h
@@ -27,12 +27,13 @@
 
 class OSystem_PS3 : public OSystem_SDL {
 public:
-	virtual void init();
-	virtual void initBackend();
+	void init() override;
+	void initBackend() override;
+	Common::HardwareInputSet *getHardwareInputSet() override;
 
 protected:
-	virtual Common::String getDefaultConfigFileName();
-	virtual Common::String getDefaultLogFileName();
+	Common::String getDefaultConfigFileName() override;
+	Common::String getDefaultLogFileName() override;
 };
 
 #endif


Commit: b3345e79a9f5d5b5b94ecadbfd3e9ff634bbb7af
    https://github.com/scummvm/scummvm/commit/b3345e79a9f5d5b5b94ecadbfd3e9ff634bbb7af
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-29T08:51:30+01:00

Commit Message:
I18N: Update POTFILES for the keymapper changes

Changed paths:
    po/POTFILES


diff --git a/po/POTFILES b/po/POTFILES
index f5e0ddd..b72a56a 100644
--- a/po/POTFILES
+++ b/po/POTFILES
@@ -63,7 +63,8 @@ backends/graphics/opengl/opengl-graphics.cpp
 backends/graphics/openglsdl/openglsdl-graphics.cpp
 backends/graphics/surfacesdl/surfacesdl-graphics.cpp
 backends/graphics/sdl/sdl-graphics.cpp
-backends/keymapper/remap-dialog.cpp
+backends/keymapper/hardware-input.cpp
+backends/keymapper/remap-widget.cpp
 backends/midi/windows.cpp
 backends/networking/sdl_net/handlers/createdirectoryhandler.cpp
 backends/networking/sdl_net/handlers/downloadfilehandler.cpp
@@ -81,6 +82,7 @@ backends/platform/ios7/ios7_osys_events.cpp
 backends/platform/iphone/osys_events.cpp
 backends/platform/maemo/maemo.cpp
 backends/platform/sdl/macosx/appmenu_osx.mm
+backends/platform/sdl/ps3/ps3.cpp
 backends/platform/symbian/src/SymbianActions.cpp
 backends/platform/tizen/form.cpp
 backends/platform/tizen/fs.cpp




More information about the Scummvm-git-logs mailing list