[Scummvm-git-logs] scummvm master -> 511d138bbcf82ea48f7242fdf2f8b5b62e494bd4

bluegr bluegr at gmail.com
Sun Jan 26 21:09:15 UTC 2020


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

Summary:
19de568e24 KEYMAPPER: Untangle the dependencies between Action and Keymap
ee8229dc00 ENGINES: Move keymap initialization to MetaEngine
be388fd9b0 BASE: Don't needlessly go through EngineMan to get the game description
8dd2b7ca39 EVENTS: Expose the primary global keymap builder
54f57568bc GUI: Expose the keymap builder function
511d138bbc KEYMAPPER: Move the remap dialog to an option dialog tab


Commit: 19de568e24e8658143116bc58d6e3740851e7a1a
    https://github.com/scummvm/scummvm/commit/19de568e24e8658143116bc58d6e3740851e7a1a
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-26T23:09:08+02:00

Commit Message:
KEYMAPPER: Untangle the dependencies between Action and Keymap

Changed paths:
    backends/keymapper/action.cpp
    backends/keymapper/action.h
    backends/keymapper/keymap.h
    backends/keymapper/remap-dialog.cpp
    backends/keymapper/remap-dialog.h
    backends/platform/maemo/maemo.cpp
    base/main.cpp
    engines/engine.cpp
    engines/kyra/engine/eobcommon.cpp
    engines/kyra/engine/lol.cpp
    engines/mohawk/riven.cpp
    engines/pegasus/pegasus.cpp
    gui/gui-manager.cpp


diff --git a/backends/keymapper/action.cpp b/backends/keymapper/action.cpp
index 50ef2ed..0b7b67a 100644
--- a/backends/keymapper/action.cpp
+++ b/backends/keymapper/action.cpp
@@ -28,12 +28,10 @@
 
 namespace Common {
 
-Action::Action(Keymap *boss, const char *i,	String des)
-	: _boss(boss), description(des), id(i) {
+Action::Action(const char *i, const String &des) :
+		id(i),
+		description(des) {
 	assert(i);
-	assert(_boss);
-
-	_boss->addAction(this);
 }
 
 void Action::addDefaultInputMapping(const String &hwId) {
diff --git a/backends/keymapper/action.h b/backends/keymapper/action.h
index 00d162b..701ae35 100644
--- a/backends/keymapper/action.h
+++ b/backends/keymapper/action.h
@@ -29,14 +29,10 @@
 
 #include "common/array.h"
 #include "common/events.h"
-#include "common/func.h"
 #include "common/str.h"
 
 namespace Common {
 
-struct HardwareInput;
-class Keymap;
-
 struct KeyActionEntry {
 	const char *id;
 	const KeyState ks;
@@ -54,12 +50,10 @@ struct Action {
 	Event event;
 
 private:
-	Keymap *_boss;
-
 	Array<String> _defaultInputMapping;
 
 public:
-	Action(Keymap *boss, const char *id, String des = "");
+	Action(const char *id, const String &description = "");
 
 	void setEvent(const Event &evt) {
 		event = evt;
@@ -103,10 +97,6 @@ public:
 		return _defaultInputMapping;
 	}
 
-	Keymap *getParent() {
-		return _boss;
-	}
-
 };
 
 } // End of namespace Common
diff --git a/backends/keymapper/keymap.h b/backends/keymapper/keymap.h
index 461b3a9..40a4e78 100644
--- a/backends/keymapper/keymap.h
+++ b/backends/keymapper/keymap.h
@@ -90,6 +90,15 @@ public:
 	const ActionArray &getMappedActions(const HardwareInput *hardwareInput) const;
 
 	/**
+	 * Adds a new Action to this Map
+	 *
+	 * Takes ownership of the action.
+	 *
+	 * @param action the Action to add
+	 */
+	void addAction(Action *action);
+
+	/**
 	 * Get the list of all the Actions contained in this Keymap
 	 */
 	const ActionArray &getActions() const { return _actions; }
@@ -117,14 +126,6 @@ public:
 	void setEnabled(bool enabled) { _enabled = enabled; }
 
 private:
-	friend struct Action;
-
-	/**
-	 * Adds a new Action to this Map,
-	 * adding it at the back of the internal array
-	 * @param action the Action to add
-	 */
-	void addAction(Action *action);
 
 	const Action *findAction(const char *id) const;
 
diff --git a/backends/keymapper/remap-dialog.cpp b/backends/keymapper/remap-dialog.cpp
index 168314d..aa59540 100644
--- a/backends/keymapper/remap-dialog.cpp
+++ b/backends/keymapper/remap-dialog.cpp
@@ -47,8 +47,11 @@ enum {
 	kReflowCmd = 'REFL'
 };
 
-RemapDialog::RemapDialog()
-	: Dialog("KeyMapper"), _remapTimeout(0), _remapAction(nullptr) {
+RemapDialog::RemapDialog() :
+		Dialog("KeyMapper"),
+		_remapKeymap(nullptr),
+		_remapAction(nullptr),
+		_remapTimeout(0) {
 
 	_keymapper = g_system->getEventManager()->getKeymapper();
 	assert(_keymapper);
@@ -162,7 +165,7 @@ void RemapDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 d
 void RemapDialog::clearMapping(uint i) {
 	debug(3, "clear the mapping %u", i);
 	Action *action = _actions[i].action;
-	Keymap *keymap = action->getParent();
+	Keymap *keymap = _actions[i].keymap;
 	keymap->unregisterMapping(action);
 
 	_changes = true;
@@ -174,7 +177,7 @@ void RemapDialog::clearMapping(uint i) {
 void RemapDialog::resetMapping(uint i) {
 	debug(3, "Reset the mapping %u", i);
 	Action *action = _actions[i].action;
-	Keymap *keymap = action->getParent();
+	Keymap *keymap = _actions[i].keymap;
 	keymap->resetMapping(action);
 
 	_changes = true;
@@ -190,6 +193,7 @@ void RemapDialog::startRemapping(uint i) {
 		return;
 	}
 
+	_remapKeymap = _actions[i].keymap;
 	_remapAction = _actions[i].action;
 	_remapTimeout = g_system->getMillis() + kRemapTimeoutDelay;
 	_remapInputWatcher->startWatching();
@@ -199,6 +203,7 @@ void RemapDialog::startRemapping(uint i) {
 }
 
 void RemapDialog::stopRemapping() {
+	_remapKeymap = nullptr;
 	_remapAction = nullptr;
 
 	refreshKeymap();
@@ -216,8 +221,7 @@ void RemapDialog::handleMouseDown(int x, int y, int button, int clickCount) {
 void RemapDialog::handleTickle() {
 	const HardwareInput *hardwareInput = _remapInputWatcher->checkForCapturedInput();
 	if (hardwareInput) {
-		Keymap *keymap = _remapAction->getParent();
-		keymap->registerMapping(_remapAction, hardwareInput);
+		_remapKeymap->registerMapping(_remapAction, hardwareInput);
 
 		_changes = true;
 		stopRemapping();
@@ -251,6 +255,7 @@ void RemapDialog::loadKeymap() {
 	Keymap *km = _keymapTable[_kmPopUp->getSelectedTag()];
 	for (Keymap::ActionArray::const_iterator it = km->getActions().begin(); it != km->getActions().end(); ++it) {
 		ActionRow row;
+		row.keymap = km;
 		row.action = *it;
 
 		_actions.push_back(row);
@@ -273,9 +278,7 @@ void RemapDialog::refreshKeymap() {
 
 		row.actionText->setLabel(row.action->description);
 
-		Keymap *keymap = row.action->getParent();
-
-		Array<const HardwareInput *> mappedInputs = keymap->getActionMapping(row.action);
+		Array<const HardwareInput *> mappedInputs = row.keymap->getActionMapping(row.action);
 
 		String keysLabel;
 		for (uint j = 0; j < mappedInputs.size(); j++) {
diff --git a/backends/keymapper/remap-dialog.h b/backends/keymapper/remap-dialog.h
index b94081d..0b1f5f7 100644
--- a/backends/keymapper/remap-dialog.h
+++ b/backends/keymapper/remap-dialog.h
@@ -55,6 +55,7 @@ public:
 
 protected:
 	struct ActionRow {
+		Keymap *keymap;
 		Common::Action *action;
 
 		GUI::StaticTextWidget *actionText;
@@ -62,7 +63,7 @@ protected:
 		GUI::ButtonWidget *clearButton;
 		GUI::ButtonWidget *resetButton;
 
-		ActionRow() : action(nullptr), actionText(nullptr), keyButton(nullptr), clearButton(nullptr), resetButton(nullptr) { }
+		ActionRow() : keymap(nullptr), action(nullptr), actionText(nullptr), keyButton(nullptr), clearButton(nullptr), resetButton(nullptr) { }
 	};
 
 	void loadKeymap();
@@ -78,6 +79,7 @@ protected:
 	Common::Array<Keymap *> _keymapTable;
 
 	InputWatcher *_remapInputWatcher;
+	Keymap *_remapKeymap;
 	Action *_remapAction;
 	uint32 _remapTimeout;
 
diff --git a/backends/platform/maemo/maemo.cpp b/backends/platform/maemo/maemo.cpp
index 5beaa48..e0cf0e6 100644
--- a/backends/platform/maemo/maemo.cpp
+++ b/backends/platform/maemo/maemo.cpp
@@ -202,20 +202,24 @@ Common::Keymap *OSystem_SDL_Maemo::getGlobalKeymap() {
 
 	Action *act;
 
-	act = new Action(globalMap, "CLKM", _("Click Mode"));
+	act = new Action("CLKM", _("Click Mode"));
 	Event evt = Event();
 	evt.type = EVENT_CUSTOM_BACKEND_ACTION;
 	evt.customType = Maemo::kEventClickMode;
 	act->setEvent(evt);
+	globalMap->addAction(act);
 
-	act = new Action(globalMap, "LCLK", _("Left Click"));
+	act = new Action("LCLK", _("Left Click"));
 	act->setLeftClickEvent();
+	globalMap->addAction(act);
 
-	act = new Action(globalMap, "MCLK", _("Middle Click"));
+	act = new Action("MCLK", _("Middle Click"));
 	act->setMiddleClickEvent();
+	globalMap->addAction(act);
 
-	act = new Action(globalMap, "RCLK", _("Right Click"));
+	act = new Action("RCLK", _("Right Click"));
 	act->setRightClickEvent();
+	globalMap->addAction(act);
 
 	return globalMap;
 }
diff --git a/base/main.cpp b/base/main.cpp
index 0c2f677..bfb9b21 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -364,33 +364,41 @@ static void setupKeymapper(OSystem &system) {
 
 	// Now create the global keymap
 	Keymap *primaryGlobalKeymap = new Keymap(Keymap::kKeymapTypeGlobal, kGlobalKeymapName);
+
 	Action *act;
-	act = new Action(primaryGlobalKeymap, "MENU", _("Menu"));
+	act = new Action("MENU", _("Menu"));
 	act->addDefaultInputMapping("C+F5");
 	act->setEvent(EVENT_MAINMENU);
+	primaryGlobalKeymap->addAction(act);
 
 #ifdef ENABLE_VKEYBD
-	act = new Action(primaryGlobalKeymap, "VIRT", _("Display keyboard"));
+	act = new Action("VIRT", _("Display keyboard"));
 	act->addDefaultInputMapping("C+F7");
 	act->setEvent(EVENT_VIRTUAL_KEYBOARD);
+	primaryGlobalKeymap->addAction(act);
 #endif
 
-	act = new Action(primaryGlobalKeymap, "REMP", _("Remap keys"));
+	act = new Action("REMP", _("Remap keys"));
 	act->addDefaultInputMapping("C+F8");
 	act->setEvent(EVENT_KEYMAPPER_REMAP);
+	primaryGlobalKeymap->addAction(act);
 
-	act = new Action(primaryGlobalKeymap, "FULS", _("Toggle fullscreen"));
+	act = new Action("FULS", _("Toggle fullscreen"));
 	act->addDefaultInputMapping("A+RETURN");
 	act->setKeyEvent(KeyState(KEYCODE_RETURN, ASCII_RETURN, KBD_ALT));
+	primaryGlobalKeymap->addAction(act);
 
-	act = new Action(primaryGlobalKeymap, "LCLK", _("Left Click"));
+	act = new Action("LCLK", _("Left Click"));
 	act->setLeftClickEvent();
+	primaryGlobalKeymap->addAction(act);
 
-	act = new Action(primaryGlobalKeymap, "MCLK", _("Middle Click"));
+	act = new Action("MCLK", _("Middle Click"));
 	act->setMiddleClickEvent();
+	primaryGlobalKeymap->addAction(act);
 
-	act = new Action(primaryGlobalKeymap, "RCLK", _("Right Click"));
+	act = new Action("RCLK", _("Right Click"));
 	act->setRightClickEvent();
+	primaryGlobalKeymap->addAction(act);
 
 	mapper->addGlobalKeymap(primaryGlobalKeymap);
 
diff --git a/engines/engine.cpp b/engines/engine.cpp
index 850ccf0..c17b1d8 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -635,9 +635,10 @@ void Engine::initKeymap() {
 	};
 
 	for (uint i = 0; i < ARRAYSIZE(keyActionEntries); i++) {
-		Common::Action *const act = new Common::Action(engineKeyMap, keyActionEntries[i].id, keyActionEntries[i].description);
+		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);
 	}
 
 	mapper->addGameKeymap(engineKeyMap);
diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
index f552a7f..2c6f199 100644
--- a/engines/kyra/engine/eobcommon.cpp
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -374,15 +374,17 @@ void EoBCoreEngine::initKeymap() {
 	};
 
 	for (uint i = 0; i < ARRAYSIZE(keyActionEntries); ++i) {
-		Common::Action *const act = new Common::Action(engineKeyMap, keyActionEntries[i].id, keyActionEntries[i].description);
+		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);
 	}
 
 	if (_flags.gameID == GI_EOB2) {
-		Common::Action *const act = new Common::Action(engineKeyMap, "SL6", _("Spell Level 6"));
+		Common::Action *const act = new Common::Action("SL6", _("Spell Level 6"));
 		act->setKeyEvent(Common::KeyState(Common::KEYCODE_6));
 		act->addDefaultInputMapping("6");
+		engineKeyMap->addAction(act);
 	}
 
 	mapper->addGameKeymap(engineKeyMap);
diff --git a/engines/kyra/engine/lol.cpp b/engines/kyra/engine/lol.cpp
index 1397369..66b48fe 100644
--- a/engines/kyra/engine/lol.cpp
+++ b/engines/kyra/engine/lol.cpp
@@ -488,9 +488,10 @@ void LoLEngine::initKeymap() {
 	};
 
 	for (const Common::KeyActionEntry *entry = keyActionEntries; entry->id; ++entry) {
-		Common::Action *const act = new Common::Action(engineKeyMap, entry->id, entry->description);
+		Common::Action *const act = new Common::Action(entry->id, entry->description);
 		act->setKeyEvent(entry->ks);
 		act->addDefaultInputMapping(entry->defaultHwId);
+		engineKeyMap->addAction(act);
 	}
 
 	mapper->addGameKeymap(engineKeyMap);
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index a02f0da..826186c 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -903,27 +903,31 @@ void MohawkEngine_Riven::initKeymap() {
 	};
 
 	for (uint i = 0; i < ARRAYSIZE(keyActionEntries); i++) {
-		Common::Action *const act = new Common::Action(engineKeyMap, keyActionEntries[i].id, keyActionEntries[i].description);
+		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);
 	}
 
 	if (getFeatures() & GF_DEMO) {
 		for (uint i = 0; i < ARRAYSIZE(keyActionEntriesDemo); i++) {
-			Common::Action* const act = new Common::Action(engineKeyMap, keyActionEntriesDemo[i].id, keyActionEntriesDemo[i].description);
+			Common::Action* const act = new Common::Action(keyActionEntriesDemo[i].id, keyActionEntriesDemo[i].description);
 			act->setKeyEvent(keyActionEntriesDemo[i].ks);
 			act->addDefaultInputMapping(keyActionEntriesDemo[i].defaultHwId);
+			engineKeyMap->addAction(act);
 		}
 	}
 
 	if (getFeatures() & GF_25TH) {
-		Common::Action* const act = new Common::Action(engineKeyMap, "SMNU", _("Skip / Open main menu"));
+		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(engineKeyMap, "SKIP", _("Skip"));
+		Common::Action* const act = new Common::Action("SKIP", _("Skip"));
 		act->setKeyEvent(Common::KEYCODE_ESCAPE);
 		act->addDefaultInputMapping("ESCAPE");
+		engineKeyMap->addAction(act);
 	}
 
 	mapper->addGameKeymap(engineKeyMap);
diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp
index 943ca26..2ca6781 100644
--- a/engines/pegasus/pegasus.cpp
+++ b/engines/pegasus/pegasus.cpp
@@ -2517,9 +2517,10 @@ void PegasusEngine::initKeymap() {
 	};
 
 	for (uint i = 0; i < ARRAYSIZE(keyActionEntries); i++) {
-		Common::Action *const act = new Common::Action(engineKeyMap, keyActionEntries[i].id, keyActionEntries[i].description);
+		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);
 	}
 
 	mapper->addGameKeymap(engineKeyMap);
diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp
index 9680d8e..f0ea22c 100644
--- a/gui/gui-manager.cpp
+++ b/gui/gui-manager.cpp
@@ -122,9 +122,10 @@ void GuiManager::initKeymap() {
 	Action *act;
 	Keymap *guiMap = new Keymap(Keymap::kKeymapTypeGui, kGuiKeymapName);
 
-	act = new Action(guiMap, "CLOS", _("Close"));
+	act = new Action("CLOS", _("Close"));
 	act->addDefaultInputMapping("ESCAPE");
 	act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE, 0));
+	guiMap->addAction(act);
 
 	mapper->addGlobalKeymap(guiMap);
 }


Commit: ee8229dc0082775955ae91d30b62cc794707c3b2
    https://github.com/scummvm/scummvm/commit/ee8229dc0082775955ae91d30b62cc794707c3b2
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-26T23:09:08+02:00

Commit Message:
ENGINES: Move keymap initialization to MetaEngine

To be able to access the keymap while the engine is not running.

Changed paths:
    base/main.cpp
    engines/engine.cpp
    engines/engine.h
    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/detection_tables.h
    engines/mohawk/mohawk.h
    engines/mohawk/riven.cpp
    engines/mohawk/riven.h
    engines/pegasus/detection.cpp
    engines/pegasus/pegasus.cpp
    engines/pegasus/pegasus.h


diff --git a/base/main.cpp b/base/main.cpp
index bfb9b21..cab806e 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -155,6 +155,7 @@ void saveLastLaunchedTarget(const Common::String &target) {
 static Common::Error runGame(const Plugin *plugin, OSystem &system, const Common::String &edebuglevels) {
 	// Determine the game data path, for validation and error messages
 	Common::FSNode dir(ConfMan.get("path"));
+	Common::String target = ConfMan.getActiveDomainName();
 	Common::Error err = Common::kNoError;
 	Engine *engine = 0;
 
@@ -179,8 +180,8 @@ static Common::Error runGame(const Plugin *plugin, OSystem &system, const Common
 	}
 
 	// Create the game engine
+	const MetaEngine &metaEngine = plugin->get<MetaEngine>();
 	if (err.getCode() == Common::kNoError) {
-		const MetaEngine &metaEngine = plugin->get<MetaEngine>();
 		// Set default values for all of the custom engine options
 		// Apparently some engines query them in their constructor, thus we
 		// need to set this up before instance creation.
@@ -200,7 +201,7 @@ static Common::Error runGame(const Plugin *plugin, OSystem &system, const Common
 		warning("%s failed to instantiate engine: %s (target '%s', path '%s')",
 			plugin->getName(),
 			err.getDesc().c_str(),
-			ConfMan.getActiveDomainName().c_str(),
+			target.c_str(),
 			dir.getPath().c_str()
 			);
 
@@ -208,7 +209,7 @@ static Common::Error runGame(const Plugin *plugin, OSystem &system, const Common
 		// so it not visible in the launcher.
 		// Temporary targets are created when starting games from the command line using the game id.
 		if (ConfMan.hasKey("id_came_from_command_line")) {
-			ConfMan.removeGameDomain(ConfMan.getActiveDomainName().c_str());
+			ConfMan.removeGameDomain(target.c_str());
 		}
 
 		return err;
@@ -218,13 +219,13 @@ static Common::Error runGame(const Plugin *plugin, OSystem &system, const Common
 	Common::String caption(ConfMan.get("description"));
 
 	if (caption.empty()) {
-		QualifiedGameDescriptor game = EngineMan.findTarget(ConfMan.getActiveDomainName());
+		QualifiedGameDescriptor game = EngineMan.findTarget(target);
 		if (!game.description.empty()) {
 			caption = game.description;
 		}
 	}
 	if (caption.empty())
-		caption = ConfMan.getActiveDomainName(); // Use the domain (=target) name
+		caption = target;
 	if (!caption.empty())	{
 		system.setWindowCaption(caption.c_str());
 	}
@@ -280,8 +281,14 @@ static Common::Error runGame(const Plugin *plugin, OSystem &system, const Common
 	}
 #endif // USE_TRANSLATION
 
+#ifdef ENABLE_KEYMAPPER
 	// Initialize any game-specific keymaps
-	engine->initKeymap();
+	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();
@@ -293,7 +300,9 @@ static Common::Error runGame(const Plugin *plugin, OSystem &system, const Common
 	system.engineDone();
 
 	// Clean up any game-specific keymaps
-	engine->deinitKeymap();
+#ifdef ENABLE_KEYMAPPER
+	keymapper->cleanupGameKeymaps();
+#endif
 
 	// Free up memory
 	delete engine;
diff --git a/engines/engine.cpp b/engines/engine.cpp
index c17b1d8..5f2c5ef 100644
--- a/engines/engine.cpp
+++ b/engines/engine.cpp
@@ -615,42 +615,6 @@ void Engine::syncSoundSettings() {
 	_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, soundVolumeSpeech);
 }
 
-void Engine::initKeymap() {
-#ifdef ENABLE_KEYMAPPER
-	static const char *const kKeymapName = "engine-default";
-	Common::Keymapper *const mapper = _eventMan->getKeymapper();
-
-	// Do not try to recreate same keymap over again
-	if (mapper->getKeymap(kKeymapName))
-		return;
-
-	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, kKeymapName);
-
-	// 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") }
-	};
-
-	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);
-	}
-
-	mapper->addGameKeymap(engineKeyMap);
-#endif
-}
-
-void Engine::deinitKeymap() {
-#ifdef ENABLE_KEYMAPPER
-	_eventMan->getKeymapper()->cleanupGameKeymaps();
-#endif
-}
-
 void Engine::flipMute() {
 	// Mute will be set to true by default here. This has two reasons:
 	// - if the game already has an "mute" config entry, it will be overwritten anyway.
diff --git a/engines/engine.h b/engines/engine.h
index af55aa9..db8cc02 100644
--- a/engines/engine.h
+++ b/engines/engine.h
@@ -205,16 +205,6 @@ public:
 	 */
 	virtual void syncSoundSettings();
 
-	/*
-	 * Initialize any engine-specific keymaps.
-	 */
-	virtual void initKeymap();
-
-	/*
-	 * Cleanup any engine-specific keymaps.
-	 */
-	virtual void deinitKeymap();
-
 	/**
 	 * Flip mute all sound option.
 	 */
diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp
index 8f37d29..5770489 100644
--- a/engines/kyra/detection.cpp
+++ b/engines/kyra/detection.cpp
@@ -182,6 +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;
 };
 
 bool KyraMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -351,6 +352,20 @@ SaveStateDescriptor KyraMetaEngine::querySaveMetaInfos(const char *target, int s
 	return desc;
 }
 
+Common::Keymap *KyraMetaEngine::initKeymap(const char *target) const {
+	Common::String gameId = ConfMan.get("gameid", target);
+
+	if (gameId.contains("lol")) {
+		return Kyra::LoLEngine::initKeymap();
+	}
+
+	if (gameId.contains("eob")) {
+		return Kyra::EoBCoreEngine::initKeymap(gameId);
+	}
+
+	return AdvancedMetaEngine::initKeymap(target);
+}
+
 #if PLUGIN_ENABLED_DYNAMIC(KYRA)
 	REGISTER_PLUGIN_DYNAMIC(KYRA, PLUGIN_TYPE_ENGINE, KyraMetaEngine);
 #else
diff --git a/engines/kyra/engine/eobcommon.cpp b/engines/kyra/engine/eobcommon.cpp
index 2c6f199..f010987 100644
--- a/engines/kyra/engine/eobcommon.cpp
+++ b/engines/kyra/engine/eobcommon.cpp
@@ -343,14 +343,8 @@ EoBCoreEngine::~EoBCoreEngine() {
 	_txt = 0;
 }
 
-void EoBCoreEngine::initKeymap() {
+Common::Keymap *EoBCoreEngine::initKeymap(const Common::String &gameId) {
 #ifdef ENABLE_KEYMAPPER
-	Common::Keymapper *const mapper = _eventMan->getKeymapper();
-
-	// Do not try to recreate same keymap over again
-	if (mapper->getKeymap(kKeymapName) != 0)
-		return;
-
 	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, kKeymapName);
 
 	const Common::KeyActionEntry keyActionEntries[] = {
@@ -380,14 +374,16 @@ void EoBCoreEngine::initKeymap() {
 		engineKeyMap->addAction(act);
 	}
 
-	if (_flags.gameID == GI_EOB2) {
+	if (gameId == "eob2") {
 		Common::Action *const act = new Common::Action("SL6", _("Spell Level 6"));
 		act->setKeyEvent(Common::KeyState(Common::KEYCODE_6));
 		act->addDefaultInputMapping("6");
 		engineKeyMap->addAction(act);
 	}
 
-	mapper->addGameKeymap(engineKeyMap);
+	return engineKeyMap;
+#else
+	return nullptr;
 #endif
 }
 
diff --git a/engines/kyra/engine/eobcommon.h b/engines/kyra/engine/eobcommon.h
index b266be7..7b4ff66 100644
--- a/engines/kyra/engine/eobcommon.h
+++ b/engines/kyra/engine/eobcommon.h
@@ -29,6 +29,10 @@
 
 #ifdef ENABLE_EOB
 
+namespace Common {
+class Keymap;
+}
+
 namespace Kyra {
 
 struct DarkMoonShapeDef {
@@ -251,7 +255,7 @@ public:
 	EoBCoreEngine(OSystem *system, const GameFlags &flags);
 	virtual ~EoBCoreEngine();
 
-	virtual void initKeymap();
+	static Common::Keymap *initKeymap(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 66b48fe..64e17c7 100644
--- a/engines/kyra/engine/lol.cpp
+++ b/engines/kyra/engine/lol.cpp
@@ -461,14 +461,8 @@ Common::Error LoLEngine::init() {
 	return Common::kNoError;
 }
 
-void LoLEngine::initKeymap() {
+Common::Keymap *LoLEngine::initKeymap() {
 #ifdef ENABLE_KEYMAPPER
-	Common::Keymapper *const mapper = _eventMan->getKeymapper();
-
-	// Do not try to recreate same keymap over again
-	if (mapper->getKeymap(kKeymapName) != 0)
-		return;
-
 	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, kKeymapName);
 
 	const Common::KeyActionEntry keyActionEntries[] = {
@@ -494,7 +488,9 @@ void LoLEngine::initKeymap() {
 		engineKeyMap->addAction(act);
 	}
 
-	mapper->addGameKeymap(engineKeyMap);
+	return engineKeyMap;
+#else
+	return nullptr;
 #endif
 }
 
diff --git a/engines/kyra/engine/lol.h b/engines/kyra/engine/lol.h
index bbaae98..11d897b 100644
--- a/engines/kyra/engine/lol.h
+++ b/engines/kyra/engine/lol.h
@@ -37,6 +37,10 @@ namespace Audio {
 class SeekableAudioStream;
 } // End of namespace Audio
 
+namespace Common {
+class Keymap;
+}
+
 namespace Kyra {
 
 class Screen_LoL;
@@ -268,7 +272,7 @@ public:
 	LoLEngine(OSystem *system, const GameFlags &flags);
 	virtual ~LoLEngine();
 
-	virtual void initKeymap();
+	static Common::Keymap *initKeymap();
 
 	void pauseEngineIntern(bool pause);
 
diff --git a/engines/metaengine.cpp b/engines/metaengine.cpp
index 46a5f12..5d120b4 100644
--- a/engines/metaengine.cpp
+++ b/engines/metaengine.cpp
@@ -22,8 +22,12 @@
 
 #include "engines/metaengine.h"
 
+#include "backends/keymapper/action.h"
+#include "backends/keymapper/keymap.h"
+
 #include "common/savefile.h"
 #include "common/system.h"
+#include "common/translation.h"
 
 #include "graphics/thumbnail.h"
 
@@ -43,6 +47,31 @@ const char *MetaEngine::getSavegamePattern(const char *target) const {
 	return buffer;
 }
 
+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,
+	// 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") }
+	};
+
+	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);
+	}
+
+	return engineKeyMap;
+#else
+	return nullptr;
+#endif
+}
+
 void MetaEngine::appendExtendedSave(Common::OutSaveFile *saveFile, uint32 playtime, Common::String desc) {
 	ExtendedSavegameHeader header;
 
diff --git a/engines/metaengine.h b/engines/metaengine.h
index dfe882a..10e5fbf 100644
--- a/engines/metaengine.h
+++ b/engines/metaengine.h
@@ -36,6 +36,7 @@ class Engine;
 class OSystem;
 
 namespace Common {
+class Keymap;
 class FSList;
 class OutSaveFile;
 class String;
@@ -216,6 +217,11 @@ public:
 	 */
 	virtual const char *getSavegamePattern(const char *target = nullptr) const;
 
+	/**
+	 * Return the keymap used by the target.
+	 */
+	virtual Common::Keymap *initKeymap(const char *target) const;
+
 	/** @name MetaEngineFeature flags */
 	//@{
 
diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp
index 96b68af..8f628cb 100644
--- a/engines/mohawk/detection.cpp
+++ b/engines/mohawk/detection.cpp
@@ -22,6 +22,9 @@
 
 #include "base/plugins.h"
 
+#include "backends/keymapper/action.h"
+#include "backends/keymapper/keymap.h"
+
 #include "engines/advancedDetector.h"
 #include "common/config-manager.h"
 #include "common/savefile.h"
@@ -223,6 +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;
 };
 
 bool MohawkMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -327,6 +331,16 @@ SaveStateDescriptor MohawkMetaEngine::querySaveMetaInfos(const char *target, int
 	}
 }
 
+Common::Keymap *MohawkMetaEngine::initKeymap(const char *target) const {
+	Common::String gameId = ConfMan.get("gameid", target);
+
+	if (gameId == "riven") {
+		return Mohawk::MohawkEngine_Riven::initKeymap(target);
+	}
+
+	return AdvancedMetaEngine::initKeymap(target);
+}
+
 bool MohawkMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
 	const Mohawk::MohawkGameDescription *gd = (const Mohawk::MohawkGameDescription *)desc;
 
diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h
index a3c0a0f..9ac74b5 100644
--- a/engines/mohawk/detection_tables.h
+++ b/engines/mohawk/detection_tables.h
@@ -22,15 +22,14 @@
 
 namespace Mohawk {
 
-#define GAMEOPTION_PLAY_MYST_FLYBY         GUIO_GAMEOPTIONS1
-
 #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_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_DEMO             GUIO5(GUIO_NOASPECT, GUIO_NOSUBTITLES, GUIO_NOSPEECH, GUIO_NOMIDI, GUIO_NOLAUNCHLOAD)
+#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)
 
 static const MohawkGameDescription gameDescriptions[] = {
 	// Myst
@@ -693,7 +692,7 @@ static const MohawkGameDescription gameDescriptions[] = {
 			Common::EN_ANY,
 			Common::kPlatformWindows,
 			ADGF_DROPPLATFORM,
-			GUI_OPTIONS_RIVEN
+			GUI_OPTIONS_RIVEN_25TH
 		},
 		GType_RIVEN,
 		GF_DVD | GF_25TH,
@@ -714,7 +713,7 @@ static const MohawkGameDescription gameDescriptions[] = {
 			Common::FR_FRA,
 			Common::kPlatformWindows,
 			ADGF_DROPPLATFORM,
-			GUI_OPTIONS_RIVEN
+			GUI_OPTIONS_RIVEN_25TH
 		},
 		GType_RIVEN,
 		GF_DVD | GF_25TH | GF_LANGUAGE_FILES,
@@ -735,7 +734,7 @@ static const MohawkGameDescription gameDescriptions[] = {
 			Common::DE_DEU,
 			Common::kPlatformWindows,
 			ADGF_DROPPLATFORM,
-			GUI_OPTIONS_RIVEN
+			GUI_OPTIONS_RIVEN_25TH
 		},
 		GType_RIVEN,
 		GF_DVD | GF_25TH | GF_LANGUAGE_FILES,
@@ -756,7 +755,7 @@ static const MohawkGameDescription gameDescriptions[] = {
 			Common::IT_ITA,
 			Common::kPlatformWindows,
 			ADGF_DROPPLATFORM,
-			GUI_OPTIONS_RIVEN
+			GUI_OPTIONS_RIVEN_25TH
 		},
 		GType_RIVEN,
 		GF_DVD | GF_25TH | GF_LANGUAGE_FILES,
@@ -777,7 +776,7 @@ static const MohawkGameDescription gameDescriptions[] = {
 			Common::JA_JPN,
 			Common::kPlatformWindows,
 			ADGF_DROPPLATFORM,
-			GUI_OPTIONS_RIVEN
+			GUI_OPTIONS_RIVEN_25TH
 		},
 		GType_RIVEN,
 		GF_DVD | GF_25TH | GF_LANGUAGE_FILES,
@@ -798,7 +797,7 @@ static const MohawkGameDescription gameDescriptions[] = {
 			Common::PL_POL,
 			Common::kPlatformWindows,
 			ADGF_DROPPLATFORM,
-			GUI_OPTIONS_RIVEN
+			GUI_OPTIONS_RIVEN_25TH
 		},
 		GType_RIVEN,
 		GF_DVD | GF_25TH | GF_LANGUAGE_FILES,
@@ -819,7 +818,7 @@ static const MohawkGameDescription gameDescriptions[] = {
 			Common::RU_RUS,
 			Common::kPlatformWindows,
 			ADGF_DROPPLATFORM,
-			GUI_OPTIONS_RIVEN
+			GUI_OPTIONS_RIVEN_25TH
 		},
 		GType_RIVEN,
 		GF_DVD | GF_25TH | GF_LANGUAGE_FILES,
@@ -840,7 +839,7 @@ static const MohawkGameDescription gameDescriptions[] = {
 			Common::ES_ESP,
 			Common::kPlatformWindows,
 			ADGF_DROPPLATFORM,
-			GUI_OPTIONS_RIVEN
+			GUI_OPTIONS_RIVEN_25TH
 		},
 		GType_RIVEN,
 		GF_DVD | GF_25TH | GF_LANGUAGE_FILES,
diff --git a/engines/mohawk/mohawk.h b/engines/mohawk/mohawk.h
index 2a2d25b..1fd2b7d 100644
--- a/engines/mohawk/mohawk.h
+++ b/engines/mohawk/mohawk.h
@@ -57,6 +57,10 @@ enum MohawkGameType {
 	GType_LIVINGBOOKSV5
 };
 
+#define GAMEOPTION_PLAY_MYST_FLYBY         GUIO_GAMEOPTIONS1
+#define GAMEOPTION_25TH                    GUIO_GAMEOPTIONS2
+#define GAMEOPTION_DEMO                    GUIO_GAMEOPTIONS3
+
 enum MohawkGameFeatures {
 	GF_ME             = (1 << 0), // Myst Masterpiece Edition
 	GF_25TH           = (1 << 1), // Myst and Riven 25th Anniversary
diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp
index 826186c..9ac9783 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -23,6 +23,7 @@
 #include "common/config-manager.h"
 #include "common/debug-channels.h"
 #include "common/events.h"
+#include "common/gui_options.h"
 #include "common/keyboard.h"
 #include "common/translation.h"
 #include "common/system.h"
@@ -873,16 +874,9 @@ void MohawkEngine_Riven::runOptionsDialog() {
 	_card->initializeZipMode();
 }
 
-void MohawkEngine_Riven::initKeymap() {
+Common::Keymap *MohawkEngine_Riven::initKeymap(const char *target) {
 #ifdef ENABLE_KEYMAPPER
-	static const char *const kKeymapName = "riven";
-	Common::Keymapper *const mapper = _eventMan->getKeymapper();
-
-	// Do not try to recreate same keymap over again
-	if (mapper->getKeymap(kKeymapName))
-		return;
-
-	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, kKeymapName);
+	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, "riven");
 
 	const Common::KeyActionEntry keyActionEntries[] = {
 		{ "UP",   Common::KEYCODE_UP,                                         "UP",       _("Move Forward")           },
@@ -909,7 +903,7 @@ void MohawkEngine_Riven::initKeymap() {
 		engineKeyMap->addAction(act);
 	}
 
-	if (getFeatures() & GF_DEMO) {
+	if (Common::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);
@@ -918,7 +912,7 @@ void MohawkEngine_Riven::initKeymap() {
 		}
 	}
 
-	if (getFeatures() & GF_25TH) {
+	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");
@@ -930,7 +924,9 @@ void MohawkEngine_Riven::initKeymap() {
 		engineKeyMap->addAction(act);
 	}
 
-	mapper->addGameKeymap(engineKeyMap);
+	return engineKeyMap;
+#else
+	return nullptr;
 #endif
 }
 
diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h
index 525248c..b5acc8b 100644
--- a/engines/mohawk/riven.h
+++ b/engines/mohawk/riven.h
@@ -33,6 +33,10 @@
 
 #include "graphics/surface.h"
 
+namespace Common {
+class Keymap;
+}
+
 namespace Mohawk {
 
 struct MohawkGameDescription;
@@ -104,6 +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);
 
 	void doFrame();
 	void processInput();
@@ -134,7 +139,6 @@ private:
 	// Variables
 	void initVars();
 
-	void initKeymap();
 	void pauseEngineIntern(bool) override;
 	uint32 sanitizeTransitionMode(uint32 mode);
 public:
diff --git a/engines/pegasus/detection.cpp b/engines/pegasus/detection.cpp
index 4bc56e7..2a23a3c 100644
--- a/engines/pegasus/detection.cpp
+++ b/engines/pegasus/detection.cpp
@@ -154,6 +154,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;
 };
 
 bool PegasusMetaEngine::hasFeature(MetaEngineFeature f) const {
@@ -188,6 +189,10 @@ 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();
+}
+
 bool PegasusMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
 	const Pegasus::PegasusGameDescription *gd = (const Pegasus::PegasusGameDescription *)desc;
 
diff --git a/engines/pegasus/pegasus.cpp b/engines/pegasus/pegasus.cpp
index 2ca6781..9fdb5da 100644
--- a/engines/pegasus/pegasus.cpp
+++ b/engines/pegasus/pegasus.cpp
@@ -2489,16 +2489,9 @@ uint PegasusEngine::getNeighborhoodCD(const NeighborhoodID neighborhood) const {
 	return 1;
 }
 
-void PegasusEngine::initKeymap() {
+Common::Keymap *PegasusEngine::initKeymap() {
 #ifdef ENABLE_KEYMAPPER
-	static const char *const kKeymapName = "pegasus";
-	Common::Keymapper *const mapper = _eventMan->getKeymapper();
-
-	// Do not try to recreate same keymap over again
-	if (mapper->getKeymap(kKeymapName) != 0)
-		return;
-
-	Common::Keymap *const engineKeyMap = new Common::Keymap(Common::Keymap::kKeymapTypeGame, kKeymapName);
+	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.
@@ -2523,7 +2516,9 @@ void PegasusEngine::initKeymap() {
 		engineKeyMap->addAction(act);
 	}
 
-	mapper->addGameKeymap(engineKeyMap);
+	return engineKeyMap;
+#else
+	return nullptr;
 #endif
 }
 
diff --git a/engines/pegasus/pegasus.h b/engines/pegasus/pegasus.h
index d10f72e..65af8c6 100644
--- a/engines/pegasus/pegasus.h
+++ b/engines/pegasus/pegasus.h
@@ -83,6 +83,7 @@ public:
 	bool canSaveGameStateCurrently();
 	Common::Error loadGameState(int slot);
 	Common::Error saveGameState(int slot, const Common::String &desc);
+	static Common::Keymap *initKeymap();
 
 	// Base classes
 	GraphicsManager *_gfx;
@@ -272,7 +273,6 @@ private:
 	void doSubChase();
 	uint getNeighborhoodCD(const NeighborhoodID neighborhood) const;
 	uint _currentCD;
-	void initKeymap();
 	InputBits getInputFilter();
 
 	// Menu


Commit: be388fd9b0d569bf77295bf113da43efc4313eb4
    https://github.com/scummvm/scummvm/commit/be388fd9b0d569bf77295bf113da43efc4313eb4
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-26T23:09:08+02:00

Commit Message:
BASE: Don't needlessly go through EngineMan to get the game description

Changed paths:
    base/main.cpp


diff --git a/base/main.cpp b/base/main.cpp
index cab806e..0b8c10f 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -219,8 +219,8 @@ static Common::Error runGame(const Plugin *plugin, OSystem &system, const Common
 	Common::String caption(ConfMan.get("description"));
 
 	if (caption.empty()) {
-		QualifiedGameDescriptor game = EngineMan.findTarget(target);
-		if (!game.description.empty()) {
+		PlainGameDescriptor game = metaEngine.findGame(ConfMan.get("gameid").c_str());
+		if (game.description) {
 			caption = game.description;
 		}
 	}


Commit: 8dd2b7ca39ac10268dd5352890dc2e23a23ae9e9
    https://github.com/scummvm/scummvm/commit/8dd2b7ca39ac10268dd5352890dc2e23a23ae9e9
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-26T23:09:08+02:00

Commit Message:
EVENTS: Expose the primary global keymap builder

Changed paths:
    backends/events/default/default-events.cpp
    backends/events/default/default-events.h
    base/main.cpp
    common/events.h


diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp
index 86c56ea..f0697c3 100644
--- a/backends/events/default/default-events.cpp
+++ b/backends/events/default/default-events.cpp
@@ -28,6 +28,7 @@
 #include "common/config-manager.h"
 #include "common/translation.h"
 #include "backends/events/default/default-events.h"
+#include "backends/keymapper/action.h"
 #include "backends/keymapper/keymapper.h"
 #include "backends/keymapper/remap-dialog.h"
 #include "backends/vkeybd/virtual-keyboard.h"
@@ -317,4 +318,52 @@ void DefaultEventManager::purgeMouseEvents() {
 	_eventQueue = filteredQueue;
 }
 
+#ifdef ENABLE_KEYMAPPER
+
+Common::Keymap *DefaultEventManager::getGlobalKeymap() {
+	using namespace Common;
+
+	// Now create the global keymap
+	Keymap *globalKeymap = new Keymap(Keymap::kKeymapTypeGlobal, kGlobalKeymapName);
+
+	Action *act;
+	act = new Action("MENU", _("Menu"));
+	act->addDefaultInputMapping("C+F5");
+	act->setEvent(EVENT_MAINMENU);
+	globalKeymap->addAction(act);
+
+#ifdef ENABLE_VKEYBD
+	act = new Action("VIRT", _("Display keyboard"));
+	act->addDefaultInputMapping("C+F7");
+	act->setEvent(EVENT_VIRTUAL_KEYBOARD);
+	globalKeymap->addAction(act);
+#endif
+
+	act = new Action("REMP", _("Remap keys"));
+	act->addDefaultInputMapping("C+F8");
+	act->setEvent(EVENT_KEYMAPPER_REMAP);
+	globalKeymap->addAction(act);
+
+	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("LCLK", _("Left Click"));
+	act->setLeftClickEvent();
+	globalKeymap->addAction(act);
+
+	act = new Action("MCLK", _("Middle Click"));
+	act->setMiddleClickEvent();
+	globalKeymap->addAction(act);
+
+	act = new Action("RCLK", _("Right Click"));
+	act->setRightClickEvent();
+	globalKeymap->addAction(act);
+
+	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 b46b1a0..ed25a2d 100644
--- a/backends/events/default/default-events.h
+++ b/backends/events/default/default-events.h
@@ -94,7 +94,8 @@ public:
 #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.
-	virtual Common::Keymapper *getKeymapper() override { return _keymapper; }
+	Common::Keymapper *getKeymapper() override { return _keymapper; }
+	Common::Keymap *getGlobalKeymap() override;
 #endif
 
 	/**
diff --git a/base/main.cpp b/base/main.cpp
index 0b8c10f..fbfb456 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -366,50 +366,15 @@ static void setupKeymapper(OSystem &system) {
 
 	// Query the backend for hardware keys and default bindings and register them
 	HardwareInputSet *inputSet = system.getHardwareInputSet();
-	const Common::KeymapperDefaultBindings *backendDefaultBindings = system.getKeymapperDefaultBindings();
+	const KeymapperDefaultBindings *backendDefaultBindings = system.getKeymapperDefaultBindings();
 
 	mapper->registerHardwareInputSet(inputSet);
 	mapper->registerBackendDefaultBindings(backendDefaultBindings);
 
-	// Now create the global keymap
-	Keymap *primaryGlobalKeymap = new Keymap(Keymap::kKeymapTypeGlobal, kGlobalKeymapName);
-
-	Action *act;
-	act = new Action("MENU", _("Menu"));
-	act->addDefaultInputMapping("C+F5");
-	act->setEvent(EVENT_MAINMENU);
-	primaryGlobalKeymap->addAction(act);
-
-#ifdef ENABLE_VKEYBD
-	act = new Action("VIRT", _("Display keyboard"));
-	act->addDefaultInputMapping("C+F7");
-	act->setEvent(EVENT_VIRTUAL_KEYBOARD);
-	primaryGlobalKeymap->addAction(act);
-#endif
-
-	act = new Action("REMP", _("Remap keys"));
-	act->addDefaultInputMapping("C+F8");
-	act->setEvent(EVENT_KEYMAPPER_REMAP);
-	primaryGlobalKeymap->addAction(act);
-
-	act = new Action("FULS", _("Toggle fullscreen"));
-	act->addDefaultInputMapping("A+RETURN");
-	act->setKeyEvent(KeyState(KEYCODE_RETURN, ASCII_RETURN, KBD_ALT));
-	primaryGlobalKeymap->addAction(act);
-
-	act = new Action("LCLK", _("Left Click"));
-	act->setLeftClickEvent();
-	primaryGlobalKeymap->addAction(act);
-
-	act = new Action("MCLK", _("Middle Click"));
-	act->setMiddleClickEvent();
-	primaryGlobalKeymap->addAction(act);
-
-	act = new Action("RCLK", _("Right Click"));
-	act->setRightClickEvent();
-	primaryGlobalKeymap->addAction(act);
-
-	mapper->addGlobalKeymap(primaryGlobalKeymap);
+	Keymap *primaryGlobalKeymap = system.getEventManager()->getGlobalKeymap();
+	if (primaryGlobalKeymap) {
+		mapper->addGlobalKeymap(primaryGlobalKeymap);
+	}
 
 	// Get the platform-specific global keymap (if it exists)
 	Keymap *platformGlobalKeymap = system.getGlobalKeymap();
diff --git a/common/events.h b/common/events.h
index f4ca5bb..13d2e89 100644
--- a/common/events.h
+++ b/common/events.h
@@ -421,6 +421,7 @@ private:
 	void dispatchPoll();
 };
 
+class Keymap;
 class Keymapper;
 
 /**
@@ -503,6 +504,7 @@ public:
 	// replacing it by a generic getScreenChangeID method here
 #ifdef ENABLE_KEYMAPPER
 	virtual Keymapper *getKeymapper() = 0;
+	virtual Keymap *getGlobalKeymap() = 0;
 #endif
 
 	enum {


Commit: 54f57568bc0d6dbd46899728c040344368804aa1
    https://github.com/scummvm/scummvm/commit/54f57568bc0d6dbd46899728c040344368804aa1
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-26T23:09:08+02:00

Commit Message:
GUI: Expose the keymap builder function

Changed paths:
    gui/gui-manager.cpp
    gui/gui-manager.h


diff --git a/gui/gui-manager.cpp b/gui/gui-manager.cpp
index f0ea22c..9549041 100644
--- a/gui/gui-manager.cpp
+++ b/gui/gui-manager.cpp
@@ -110,23 +110,32 @@ GuiManager::~GuiManager() {
 }
 
 #ifdef ENABLE_KEYMAPPER
-void GuiManager::initKeymap() {
-	using namespace Common;
 
-	Keymapper *mapper = _system->getEventManager()->getKeymapper();
+Common::Keymap *GuiManager::getKeymap() const {
+	using namespace Common;
 
-	// Do not try to recreate same keymap over again
-	if (mapper->getKeymap(kGuiKeymapName) != 0)
-		return;
+	Keymap *guiMap = new Keymap(Keymap::kKeymapTypeGui, kGuiKeymapName);
 
 	Action *act;
-	Keymap *guiMap = new Keymap(Keymap::kKeymapTypeGui, kGuiKeymapName);
 
 	act = new Action("CLOS", _("Close"));
 	act->addDefaultInputMapping("ESCAPE");
 	act->setKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE, 0));
 	guiMap->addAction(act);
 
+	return guiMap;
+}
+
+void GuiManager::initKeymap() {
+	using namespace Common;
+
+	Keymapper *mapper = _system->getEventManager()->getKeymapper();
+
+	// Do not try to recreate same keymap over again
+	if (mapper->getKeymap(kGuiKeymapName) != 0)
+		return;
+
+	Keymap *guiMap = getKeymap();
 	mapper->addGlobalKeymap(guiMap);
 }
 
diff --git a/gui/gui-manager.h b/gui/gui-manager.h
index d20ade3..88470f0 100644
--- a/gui/gui-manager.h
+++ b/gui/gui-manager.h
@@ -39,6 +39,7 @@ class Font;
 
 namespace Common {
 	struct Event;
+	class Keymap;
 }
 
 namespace GUI {
@@ -75,6 +76,7 @@ public:
 	void runLoop();
 
 	void processEvent(const Common::Event &event, Dialog *const activeDialog);
+	Common::Keymap *getKeymap() const;
 	void scheduleTopDialogRedraw();
 
 	bool isActive() const	{ return ! _dialogStack.empty(); }


Commit: 511d138bbcf82ea48f7242fdf2f8b5b62e494bd4
    https://github.com/scummvm/scummvm/commit/511d138bbcf82ea48f7242fdf2f8b5b62e494bd4
Author: Bastien Bouclet (bastien.bouclet at gmail.com)
Date: 2020-01-26T23:09:08+02:00

Commit Message:
KEYMAPPER: Move the remap dialog to an option dialog tab

The aim is to make it easy to discover, and possible to use without a
keyboard.

Changed paths:
  A backends/keymapper/remap-widget.cpp
  A backends/keymapper/remap-widget.h
  R backends/keymapper/remap-dialog.cpp
  R backends/keymapper/remap-dialog.h
    backends/events/default/default-events.cpp
    backends/keymapper/keymapper.cpp
    backends/keymapper/keymapper.h
    backends/module.mk
    common/EventMapper.cpp
    common/events.h
    gui/ThemeEngine.h
    gui/editgamedialog.cpp
    gui/options.cpp
    gui/options.h
    gui/themes/default.inc
    gui/themes/scummclassic.zip
    gui/themes/scummclassic/THEMERC
    gui/themes/scummclassic/classic_layout.stx
    gui/themes/scummclassic/classic_layout_lowres.stx
    gui/themes/scummmodern.zip
    gui/themes/scummmodern/THEMERC
    gui/themes/scummmodern/scummmodern_layout.stx
    gui/themes/scummmodern/scummmodern_layout_lowres.stx
    gui/themes/scummremastered.zip
    gui/themes/scummremastered/THEMERC
    gui/themes/scummremastered/remastered_layout.stx
    gui/themes/scummremastered/remastered_layout_lowres.stx


diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp
index f0697c3..ae782bb 100644
--- a/backends/events/default/default-events.cpp
+++ b/backends/events/default/default-events.cpp
@@ -30,7 +30,7 @@
 #include "backends/events/default/default-events.h"
 #include "backends/keymapper/action.h"
 #include "backends/keymapper/keymapper.h"
-#include "backends/keymapper/remap-dialog.h"
+#include "backends/keymapper/remap-widget.h"
 #include "backends/vkeybd/virtual-keyboard.h"
 
 #include "engines/engine.h"
@@ -170,20 +170,6 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
 		}
 		break;
 #endif
-#ifdef ENABLE_KEYMAPPER
-	case Common::EVENT_KEYMAPPER_REMAP:
-		if (!_remap) {
-			_remap = true;
-			Common::RemapDialog _remapDialog;
-			if (g_engine)
-				g_engine->pauseEngine(true);
-			_remapDialog.runModal();
-			if (g_engine)
-				g_engine->pauseEngine(false);
-			_remap = false;
-		}
-		break;
-#endif
 	case Common::EVENT_RTL:
 		if (ConfMan.getBool("confirm_exit")) {
 			if (g_engine)
@@ -339,11 +325,6 @@ Common::Keymap *DefaultEventManager::getGlobalKeymap() {
 	globalKeymap->addAction(act);
 #endif
 
-	act = new Action("REMP", _("Remap keys"));
-	act->addDefaultInputMapping("C+F8");
-	act->setEvent(EVENT_KEYMAPPER_REMAP);
-	globalKeymap->addAction(act);
-
 	act = new Action("FULS", _("Toggle fullscreen"));
 	act->addDefaultInputMapping("A+RETURN");
 	act->setKeyEvent(KeyState(KEYCODE_RETURN, ASCII_RETURN, KBD_ALT));
diff --git a/backends/keymapper/keymapper.cpp b/backends/keymapper/keymapper.cpp
index 2de9c9b..f9e595b 100644
--- a/backends/keymapper/keymapper.cpp
+++ b/backends/keymapper/keymapper.cpp
@@ -128,6 +128,12 @@ Keymap *Keymapper::getKeymap(const String &name) {
 	return nullptr;
 }
 
+void Keymapper::reloadAllMappings() {
+	for (uint i = 0; i < _keymaps.size(); i++) {
+		_keymaps[i]->loadMappings();
+	}
+}
+
 void Keymapper::setEnabledKeymapType(Keymap::KeymapType type) {
 	_enabledKeymapType = type;
 }
diff --git a/backends/keymapper/keymapper.h b/backends/keymapper/keymapper.h
index 3289e7d..4c4a9f1 100644
--- a/backends/keymapper/keymapper.h
+++ b/backends/keymapper/keymapper.h
@@ -43,6 +43,8 @@ class HardwareInput;
 class HardwareInputSet;
 class KeymapperDefaultBindings;
 
+typedef Array<Keymap *> KeymapArray;
+
 class Keymapper : public Common::DefaultEventMapper {
 public:
 
@@ -98,7 +100,12 @@ public:
 	/**
 	 * Obtain a list of all the keymaps registered with the keymapper
 	 */
-	const Array<Keymap *> &getKeymaps() const { return _keymaps; }
+	const KeymapArray &getKeymaps() const { return _keymaps; }
+
+	/**
+	 * reload the mappings for all the keymaps from the configuration manager
+	 */
+	void reloadAllMappings();
 
 	/**
 	 * Set which kind of keymap is currently used to map events
@@ -117,6 +124,8 @@ public:
 	 */
 	const HardwareInput *findHardwareInput(const Event &event);
 
+	void initKeymap(Keymap *keymap, ConfigManager::Domain *domain);
+
 private:
 
 	enum IncomingEventType {
@@ -125,8 +134,6 @@ private:
 		kIncomingNonKey
 	};
 
-	void initKeymap(Keymap *keymap, ConfigManager::Domain *domain);
-
 	HardwareInputSet *_hardwareInputs;
 	const KeymapperDefaultBindings *_backendDefaultBindings;
 
@@ -139,7 +146,6 @@ private:
 	bool _enabled;
 	Keymap::KeymapType _enabledKeymapType;
 
-	typedef Array<Keymap *> KeymapArray;
 	KeymapArray _keymaps;
 
 };
diff --git a/backends/keymapper/remap-dialog.cpp b/backends/keymapper/remap-dialog.cpp
deleted file mode 100644
index aa59540..0000000
--- a/backends/keymapper/remap-dialog.cpp
+++ /dev/null
@@ -1,307 +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 "backends/keymapper/remap-dialog.h"
-
-#ifdef ENABLE_KEYMAPPER
-
-#include "backends/keymapper/action.h"
-#include "backends/keymapper/hardware-input.h"
-#include "backends/keymapper/input-watcher.h"
-#include "backends/keymapper/keymap.h"
-#include "backends/keymapper/keymapper.h"
-
-#include "common/system.h"
-#include "gui/gui-manager.h"
-#include "gui/widgets/popup.h"
-#include "gui/widgets/scrollcontainer.h"
-#include "gui/ThemeEval.h"
-#include "common/translation.h"
-
-namespace Common {
-
-enum {
-	kRemapCmd  = 'REMP',
-	kClearCmd  = 'CLER',
-	kResetCmd  = 'RSET',
-	kCloseCmd  = 'CLOS',
-	kReflowCmd = 'REFL'
-};
-
-RemapDialog::RemapDialog() :
-		Dialog("KeyMapper"),
-		_remapKeymap(nullptr),
-		_remapAction(nullptr),
-		_remapTimeout(0) {
-
-	_keymapper = g_system->getEventManager()->getKeymapper();
-	assert(_keymapper);
-
-	EventDispatcher *eventDispatcher = g_system->getEventManager()->getEventDispatcher();
-	_remapInputWatcher = new InputWatcher(eventDispatcher, _keymapper);
-
-	_kmPopUpDesc = new GUI::StaticTextWidget(this, "KeyMapper.PopupDesc", _("Keymap:"));
-	_kmPopUp = new GUI::PopUpWidget(this, "KeyMapper.Popup");
-
-	_scrollContainer = new GUI::ScrollContainerWidget(this, "KeyMapper.KeymapArea", "", kReflowCmd);
-	_scrollContainer->setTarget(this);
-
-	new GUI::ButtonWidget(this, "KeyMapper.Close", _("Close"), 0, kCloseCmd);
-}
-
-RemapDialog::~RemapDialog() {
-	delete _remapInputWatcher;
-}
-
-void RemapDialog::open() {
-	_keymapTable = _keymapper->getKeymaps();
-
-	debug(3, "RemapDialog::open keymaps: %d", _keymapTable.size());
-
-	// Show the keymaps by order of priority (game keymaps first)
-	for (int i = _keymapTable.size() - 1; i >= 0; i--) {
-		_kmPopUp->appendEntry(_keymapTable[i]->getName(), i);
-	}
-
-	_changes = false;
-
-	_kmPopUp->setSelected(0);
-
-	loadKeymap();
-	refreshKeymap();
-	reflowActionWidgets();
-
-	Dialog::open();
-}
-
-void RemapDialog::close() {
-	_kmPopUp->clearEntries();
-
-	if (_changes) {
-		const Array<Keymap *> &keymaps = _keymapper->getKeymaps();
-		for (uint i = 0; i < keymaps.size(); i++) {
-			keymaps[i]->saveMappings();
-		}
-
-		ConfMan.flushToDisk();
-	}
-
-	Dialog::close();
-}
-
-void RemapDialog::reflowActionWidgets() {
-	int buttonHeight = g_gui.xmlEval()->getVar("Globals.Button.Height", 0);
-
-	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);
-
-	uint textYOff = (buttonHeight - kLineHeight) / 2;
-	uint clearButtonYOff = (buttonHeight - clearButtonHeight) / 2;
-
-	for (uint i = 0; i < _actions.size(); i++) {
-		ActionRow &row = _actions[i];
-		uint y = spacing + (i) * (buttonHeight + spacing);
-
-		uint x = spacing;
-		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);
-	}
-}
-
-void RemapDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
-	debug(3, "RemapDialog::handleCommand %u %u", cmd, data);
-
-	if (cmd >= kRemapCmd && cmd < kRemapCmd + _actions.size()) {
-		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 == kCloseCmd) {
-		close();
-	} else if (cmd == kReflowCmd) {
-		reflowActionWidgets();
-	} else if (cmd == GUI::kPopUpItemSelectedCmd) {
-		clearKeymap();
-		loadKeymap();
-		refreshKeymap();
-		_scrollContainer->reflowLayout();
-		g_gui.scheduleTopDialogRedraw();
-	} else {
-		GUI::Dialog::handleCommand(sender, cmd, data);
-	}
-}
-
-void RemapDialog::clearMapping(uint i) {
-	debug(3, "clear the mapping %u", i);
-	Action *action = _actions[i].action;
-	Keymap *keymap = _actions[i].keymap;
-	keymap->unregisterMapping(action);
-
-	_changes = true;
-
-	stopRemapping();
-	refreshKeymap();
-}
-
-void RemapDialog::resetMapping(uint i) {
-	debug(3, "Reset the mapping %u", i);
-	Action *action = _actions[i].action;
-	Keymap *keymap = _actions[i].keymap;
-	keymap->resetMapping(action);
-
-	_changes = true;
-
-	stopRemapping();
-	refreshKeymap();
-}
-
-void RemapDialog::startRemapping(uint i) {
-	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;
-	_remapTimeout = g_system->getMillis() + kRemapTimeoutDelay;
-	_remapInputWatcher->startWatching();
-
-	_actions[i].keyButton->setLabel("...");
-	_actions[i].keyButton->markAsDirty();
-}
-
-void RemapDialog::stopRemapping() {
-	_remapKeymap = nullptr;
-	_remapAction = nullptr;
-
-	refreshKeymap();
-
-	_remapInputWatcher->stopWatching();
-}
-
-void RemapDialog::handleMouseDown(int x, int y, int button, int clickCount) {
-	if (_remapInputWatcher->isWatching())
-		stopRemapping();
-	else
-		Dialog::handleMouseDown(x, y, button, clickCount);
-}
-
-void RemapDialog::handleTickle() {
-	const HardwareInput *hardwareInput = _remapInputWatcher->checkForCapturedInput();
-	if (hardwareInput) {
-		_remapKeymap->registerMapping(_remapAction, hardwareInput);
-
-		_changes = true;
-		stopRemapping();
-	}
-
-	if (_remapInputWatcher->isWatching() && g_system->getMillis() > _remapTimeout)
-		stopRemapping();
-	Dialog::handleTickle();
-}
-
-void RemapDialog::clearKeymap() {
-	for (uint i = 0; i < _actions.size(); i++) {
-		if (_actions[i].keyButton)   _scrollContainer->removeWidget(_actions[i].keyButton);
-		if (_actions[i].actionText)  _scrollContainer->removeWidget(_actions[i].actionText);
-		if (_actions[i].clearButton) _scrollContainer->removeWidget(_actions[i].clearButton);
-		if (_actions[i].resetButton) _scrollContainer->removeWidget(_actions[i].resetButton);
-
-		delete _actions[i].keyButton;
-		delete _actions[i].actionText;
-		delete _actions[i].clearButton;
-		delete _actions[i].resetButton;
-	}
-
-	_actions.clear();
-}
-
-void RemapDialog::loadKeymap() {
-	assert(_actions.empty());
-	assert(_kmPopUp->getSelected() != -1);
-
-	Keymap *km = _keymapTable[_kmPopUp->getSelectedTag()];
-	for (Keymap::ActionArray::const_iterator it = km->getActions().begin(); it != km->getActions().end(); ++it) {
-		ActionRow row;
-		row.keymap = km;
-		row.action = *it;
-
-		_actions.push_back(row);
-	}
-}
-
-void RemapDialog::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);
-			row.keyButton = new GUI::ButtonWidget(_scrollContainer, 0, 0, 0, 0, "", 0, 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.actionText->setLabel(row.action->description);
-
-		Array<const HardwareInput *> mappedInputs = row.keymap->getActionMapping(row.action);
-
-		String keysLabel;
-		for (uint j = 0; j < mappedInputs.size(); j++) {
-			if (!keysLabel.empty()) {
-				keysLabel += ", ";
-			}
-
-			keysLabel += mappedInputs[j]->description;
-		}
-
-		if (!keysLabel.empty()) {
-			row.keyButton->setLabel(keysLabel);
-			row.keyButton->setTooltip(keysLabel);
-		} else {
-			row.keyButton->setLabel("-");
-		}
-
-		// I18N: Button to reset key mapping to defaults
-		row.resetButton->setLabel(_("R"));
-		row.resetButton->setTooltip(_("Reset to defaults"));
-	}
-}
-
-} // End of namespace Common
-
-#endif // #ifdef ENABLE_KEYMAPPER
diff --git a/backends/keymapper/remap-dialog.h b/backends/keymapper/remap-dialog.h
deleted file mode 100644
index 0b1f5f7..0000000
--- a/backends/keymapper/remap-dialog.h
+++ /dev/null
@@ -1,101 +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.
- *
- */
-
-#ifndef REMAP_DIALOG_H
-#define REMAP_DIALOG_H
-
-#include "common/scummsys.h"
-
-#ifdef ENABLE_KEYMAPPER
-
-#include "gui/dialog.h"
-
-namespace GUI {
-class ButtonWidget;
-class PopUpWidget;
-class ScrollContainerWidget;
-class StaticTextWidget;
-}
-
-namespace Common {
-
-class Action;
-class Keymap;
-class Keymapper;
-class InputWatcher;
-
-class RemapDialog : public GUI::Dialog {
-public:
-	RemapDialog();
-	virtual ~RemapDialog();
-	virtual void open();
-	virtual void close();
-	virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data);
-	virtual void handleMouseDown(int x, int y, int button, int clickCount);
-	virtual void handleTickle();
-
-protected:
-	struct ActionRow {
-		Keymap *keymap;
-		Common::Action *action;
-
-		GUI::StaticTextWidget *actionText;
-		GUI::ButtonWidget *keyButton;
-		GUI::ButtonWidget *clearButton;
-		GUI::ButtonWidget *resetButton;
-
-		ActionRow() : keymap(nullptr), action(nullptr), actionText(nullptr), keyButton(nullptr), clearButton(nullptr), resetButton(nullptr) { }
-	};
-
-	void loadKeymap();
-	void refreshKeymap();
-	void clearKeymap();
-	void reflowActionWidgets();
-	void clearMapping(uint i);
-	void resetMapping(uint i);
-	void startRemapping(uint i);
-	void stopRemapping();
-
-	Keymapper *_keymapper;
-	Common::Array<Keymap *> _keymapTable;
-
-	InputWatcher *_remapInputWatcher;
-	Keymap *_remapKeymap;
-	Action *_remapAction;
-	uint32 _remapTimeout;
-
-	GUI::StaticTextWidget *_kmPopUpDesc;
-	GUI::PopUpWidget *_kmPopUp;
-	GUI::ScrollContainerWidget *_scrollContainer;
-
-	static const uint32 kRemapTimeoutDelay = 3000;
-
-	bool _changes;
-
-	Array<ActionRow> _actions;
-};
-
-} // End of namespace Common
-
-#endif // #ifdef ENABLE_KEYMAPPER
-
-#endif // #ifndef REMAP_DIALOG_H
diff --git a/backends/keymapper/remap-widget.cpp b/backends/keymapper/remap-widget.cpp
new file mode 100644
index 0000000..bf58463
--- /dev/null
+++ b/backends/keymapper/remap-widget.cpp
@@ -0,0 +1,311 @@
+/* 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/remap-widget.h"
+
+#ifdef ENABLE_KEYMAPPER
+
+#include "backends/keymapper/action.h"
+#include "backends/keymapper/hardware-input.h"
+#include "backends/keymapper/input-watcher.h"
+#include "backends/keymapper/keymap.h"
+#include "backends/keymapper/keymapper.h"
+
+#include "common/system.h"
+#include "gui/gui-manager.h"
+#include "gui/widgets/scrollcontainer.h"
+#include "gui/ThemeEval.h"
+#include "common/translation.h"
+
+namespace Common {
+
+enum {
+	kRemapCmd  = 'REMP',
+	kClearCmd  = 'CLER',
+	kResetCmd  = 'RSET',
+	kCloseCmd  = 'CLOS',
+	kReflowCmd = 'REFL'
+};
+
+RemapWidget::RemapWidget(GuiObject *boss, const Common::String &name, const KeymapArray &keymaps) :
+		Widget(boss, name),
+		_keymapTable(keymaps),
+		_remapKeymap(nullptr),
+		_remapAction(nullptr),
+		_remapTimeout(0) {
+
+	Keymapper *keymapper = g_system->getEventManager()->getKeymapper();
+	assert(keymapper);
+
+	EventDispatcher *eventDispatcher = g_system->getEventManager()->getEventDispatcher();
+	_remapInputWatcher = new InputWatcher(eventDispatcher, keymapper);
+
+	_scrollContainer = new GUI::ScrollContainerWidget(this, 0, 0, 0, 0, kReflowCmd);
+	_scrollContainer->setTarget(this);
+	_scrollContainer->setBackgroundType(GUI::ThemeEngine::kWidgetBackgroundNo);
+}
+
+RemapWidget::~RemapWidget() {
+	for (uint i = 0; i < _keymapTable.size(); i++) {
+		delete _keymapTable[i];
+	}
+	delete _remapInputWatcher;
+}
+
+void RemapWidget::build() {
+	debug(3, "RemapWidget::build keymaps: %d", _keymapTable.size());
+
+	_changes = false;
+
+	loadKeymap();
+	refreshKeymap();
+	reflowActionWidgets();
+}
+
+bool RemapWidget::save() {
+	bool changes = _changes;
+
+	if (_changes) {
+		for (uint i = 0; i < _keymapTable.size(); i++) {
+			_keymapTable[i]->saveMappings();
+		}
+		_changes = false;
+	}
+
+	return changes;
+}
+
+void RemapWidget::reflowActionWidgets() {
+	int buttonHeight = g_gui.xmlEval()->getVar("Globals.Button.Height", 0);
+
+	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);
+
+	uint textYOff = (buttonHeight - kLineHeight) / 2;
+	uint clearButtonYOff = (buttonHeight - clearButtonHeight) / 2;
+
+	uint y = spacing;
+
+	Keymap *previousKeymap = nullptr;
+
+	for (uint i = 0; i < _actions.size(); i++) {
+		uint x;
+
+		ActionRow &row = _actions[i];
+
+		if (previousKeymap != row.keymap) {
+			previousKeymap = row.keymap;
+
+			// Insert a keymap separator
+			x = 4 * spacing + keyButtonWidth + 2 * clearButtonWidth;
+
+			GUI::StaticTextWidget *serarator = _keymapSeparators[row.keymap];
+			serarator->resize(x, y, getWidth() - x - spacing, kLineHeight);
+
+			y += kLineHeight + spacing;
+		}
+
+		x = spacing;
+
+		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;
+	}
+}
+
+void RemapWidget::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
+	debug(3, "RemapWidget::handleCommand %u %u", cmd, data);
+
+	if (cmd >= kRemapCmd && cmd < kRemapCmd + _actions.size()) {
+		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 == kReflowCmd) {
+		reflowActionWidgets();
+	} else {
+		Widget::handleCommand(sender, cmd, data);
+	}
+}
+
+void RemapWidget::clearMapping(uint i) {
+	debug(3, "clear the mapping %u", i);
+	Action *action = _actions[i].action;
+	Keymap *keymap = _actions[i].keymap;
+	keymap->unregisterMapping(action);
+
+	_changes = true;
+
+	stopRemapping();
+	refreshKeymap();
+}
+
+void RemapWidget::resetMapping(uint i) {
+	debug(3, "Reset the mapping %u", i);
+	Action *action = _actions[i].action;
+	Keymap *keymap = _actions[i].keymap;
+	keymap->resetMapping(action);
+
+	_changes = true;
+
+	stopRemapping();
+	refreshKeymap();
+}
+
+void RemapWidget::startRemapping(uint i) {
+	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;
+	_remapTimeout = g_system->getMillis() + kRemapTimeoutDelay;
+	_remapInputWatcher->startWatching();
+
+	_actions[i].keyButton->setLabel("...");
+	_actions[i].keyButton->markAsDirty();
+}
+
+void RemapWidget::stopRemapping() {
+	_remapKeymap = nullptr;
+	_remapAction = nullptr;
+
+	refreshKeymap();
+
+	_remapInputWatcher->stopWatching();
+}
+
+void RemapWidget::handleMouseDown(int x, int y, int button, int clickCount) {
+	if (_remapInputWatcher->isWatching())
+		stopRemapping();
+	else
+		Widget::handleMouseDown(x, y, button, clickCount);
+}
+
+void RemapWidget::handleTickle() {
+	const HardwareInput *hardwareInput = _remapInputWatcher->checkForCapturedInput();
+	if (hardwareInput) {
+		_remapKeymap->registerMapping(_remapAction, hardwareInput);
+
+		_changes = true;
+		stopRemapping();
+	}
+
+	if (_remapInputWatcher->isWatching() && g_system->getMillis() > _remapTimeout)
+		stopRemapping();
+
+	Widget::handleTickle();
+}
+
+void RemapWidget::loadKeymap() {
+	assert(_actions.empty());
+
+	for (KeymapArray::const_iterator km = _keymapTable.begin(); km != _keymapTable.end(); km++) {
+		for (Keymap::ActionArray::const_iterator it = (*km)->getActions().begin(); it != (*km)->getActions().end(); ++it) {
+			ActionRow row;
+			row.keymap = *km;
+			row.action = *it;
+
+			_actions.push_back(row);
+		}
+	}
+}
+
+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, "", 0, 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.actionText->setLabel(row.action->description);
+
+		Array<const HardwareInput *> mappedInputs = row.keymap->getActionMapping(row.action);
+
+		String keysLabel;
+		for (uint j = 0; j < mappedInputs.size(); j++) {
+			if (!keysLabel.empty()) {
+				keysLabel += ", ";
+			}
+
+			keysLabel += mappedInputs[j]->description;
+		}
+
+		if (!keysLabel.empty()) {
+			row.keyButton->setLabel(keysLabel);
+			row.keyButton->setTooltip(keysLabel);
+		} else {
+			row.keyButton->setLabel("-");
+		}
+
+		// I18N: Button to reset key mapping to defaults
+		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->getName(), Graphics::kTextAlignLeft);
+		}
+	}
+}
+
+void RemapWidget::reflowLayout() {
+	Widget::reflowLayout();
+
+	_scrollContainer->resize(_x, _y, _w, _h);
+
+	Widget *w = _firstWidget;
+	while (w) {
+		w->reflowLayout();
+		w = w->next();
+	}
+}
+
+GUI::Widget *RemapWidget::findWidget(int x, int y) {
+	// Iterate over all child widgets and find the one which was clicked
+	return Widget::findWidgetInChain(_firstWidget, x, y);
+}
+
+} // End of namespace Common
+
+#endif // #ifdef ENABLE_KEYMAPPER
diff --git a/backends/keymapper/remap-widget.h b/backends/keymapper/remap-widget.h
new file mode 100644
index 0000000..a2bc012
--- /dev/null
+++ b/backends/keymapper/remap-widget.h
@@ -0,0 +1,106 @@
+/* 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 REMAP_WIDGET_H
+#define REMAP_WIDGET_H
+
+#include "common/scummsys.h"
+
+#ifdef ENABLE_KEYMAPPER
+
+#include "common/hash-ptr.h"
+
+#include "gui/widget.h"
+
+namespace GUI {
+class ButtonWidget;
+class PopUpWidget;
+class ScrollContainerWidget;
+class StaticTextWidget;
+}
+
+namespace Common {
+
+class Action;
+class Keymap;
+class Keymapper;
+class InputWatcher;
+
+class RemapWidget : public GUI::Widget {
+public:
+	typedef Common::Array<Keymap *> KeymapArray;
+
+	RemapWidget(GuiObject *boss, const Common::String &name, const KeymapArray &keymaps);
+	~RemapWidget() override;
+	void build();
+	bool save();
+	void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) override;
+	void handleMouseDown(int x, int y, int button, int clickCount) override;
+	void handleTickle() override;
+
+protected:
+	struct ActionRow {
+		Keymap *keymap;
+		Common::Action *action;
+
+		GUI::StaticTextWidget *actionText;
+		GUI::ButtonWidget *keyButton;
+		GUI::ButtonWidget *clearButton;
+		GUI::ButtonWidget *resetButton;
+
+		ActionRow() : keymap(nullptr), action(nullptr), actionText(nullptr), keyButton(nullptr), clearButton(nullptr), resetButton(nullptr) { }
+	};
+
+	void drawWidget() override {}
+	void reflowLayout() override;
+	Widget *findWidget(int x, int y) override;
+
+	void loadKeymap();
+	void refreshKeymap();
+	void reflowActionWidgets();
+	void clearMapping(uint i);
+	void resetMapping(uint i);
+	void startRemapping(uint i);
+	void stopRemapping();
+
+	KeymapArray _keymapTable;
+
+	InputWatcher *_remapInputWatcher;
+	Keymap *_remapKeymap;
+	Action *_remapAction;
+	uint32 _remapTimeout;
+
+	GUI::ScrollContainerWidget *_scrollContainer;
+
+	static const uint32 kRemapTimeoutDelay = 3000;
+
+	bool _changes;
+
+	Array<ActionRow> _actions;
+	HashMap<Keymap *, GUI::StaticTextWidget *> _keymapSeparators;
+};
+
+} // End of namespace Common
+
+#endif // #ifdef ENABLE_KEYMAPPER
+
+#endif // #ifndef REMAP_WIDGET_H
diff --git a/backends/module.mk b/backends/module.mk
index 21bae7e..db01661 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -108,7 +108,7 @@ MODULE_OBJS += \
 	keymapper/input-watcher.o \
 	keymapper/keymap.o \
 	keymapper/keymapper.o \
-	keymapper/remap-dialog.o
+	keymapper/remap-widget.o
 endif
 
 ifdef ENABLE_VKEYBD
diff --git a/common/EventMapper.cpp b/common/EventMapper.cpp
index 203a6e0..7693ace 100644
--- a/common/EventMapper.cpp
+++ b/common/EventMapper.cpp
@@ -63,14 +63,6 @@ List<Event> DefaultEventMapper::mapEvent(const Event &ev, EventSource *source) {
 			addDelayedEvent(100, ev);
 		}
 #endif
-#ifdef ENABLE_KEYMAPPER
-		else if (ev.kbd.hasFlags(KBD_CTRL) && ev.kbd.keycode == KEYCODE_F8) {
-			mappedEvent.type = EVENT_KEYMAPPER_REMAP;
-
-			// Avoid blocking CTRL-F8 events from engine.
-			addDelayedEvent(100, ev);
-		}
-#endif
 	}
 
 	if (ev.type == EVENT_JOYBUTTON_DOWN) {
diff --git a/common/events.h b/common/events.h
index 13d2e89..22b4743 100644
--- a/common/events.h
+++ b/common/events.h
@@ -79,7 +79,6 @@ enum EventType {
 	// this, please talk to tsoliman and/or LordHoto.
 	EVENT_CUSTOM_BACKEND_ACTION = 18,
 	EVENT_CUSTOM_BACKEND_HARDWARE = 21,
-	EVENT_KEYMAPPER_REMAP = 19,
 #endif
 #ifdef ENABLE_VKEYBD
 	EVENT_VIRTUAL_KEYBOARD = 20,
diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h
index e838063..8a218fd 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -37,7 +37,7 @@
 #include "graphics/pixelformat.h"
 
 
-#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.31"
+#define SCUMMVM_THEME_VERSION_STR "SCUMMVM_STX0.8.32"
 
 class OSystem;
 
diff --git a/gui/editgamedialog.cpp b/gui/editgamedialog.cpp
index 0028564..0ef3fa0 100644
--- a/gui/editgamedialog.cpp
+++ b/gui/editgamedialog.cpp
@@ -22,6 +22,8 @@
 
 #include "gui/editgamedialog.h"
 
+#include "backends/keymapper/keymapper.h"
+
 #include "common/config-manager.h"
 #include "common/gui_options.h"
 #include "common/translation.h"
@@ -196,6 +198,28 @@ EditGameDialog::EditGameDialog(const String &domain)
 	addGraphicControls(graphicsContainer, "GameOptions_Graphics_Container.");
 
 	//
+	// The Keymap tab
+	//
+#ifdef ENABLE_KEYMAPPER
+	Common::Keymap *keymap = nullptr;
+	if (plugin) {
+		keymap = plugin->get<MetaEngine>().initKeymap(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);
+
+		tab->addTab(_("Keymaps"), "GameOptions_KeyMapper");
+		addKeyMapperControls(tab, "GameOptions_KeyMapper.", keymaps);
+	}
+#endif
+
+	//
 	// 4) The audio tab
 	//
 	tab->addTab(_("Audio"), "GameOptions_Audio");
diff --git a/gui/options.cpp b/gui/options.cpp
index 3cd0106..c81f23f 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -30,6 +30,9 @@
 #include "gui/ThemeEval.h"
 #include "gui/launcher.h"
 
+#include "backends/keymapper/keymapper.h"
+#include "backends/keymapper/remap-widget.h"
+
 #include "common/fs.h"
 #include "common/config-manager.h"
 #include "common/gui_options.h"
@@ -156,6 +159,7 @@ void OptionsDialog::init() {
 	_joystickDeadzoneDesc = nullptr;
 	_joystickDeadzoneSlider = nullptr;
 	_joystickDeadzoneLabel = nullptr;
+	_keymapperWidget = nullptr;
 	_enableGraphicSettings = false;
 	_gfxPopUp = nullptr;
 	_gfxPopUpDesc = nullptr;
@@ -263,6 +267,13 @@ void OptionsDialog::build() {
 		}
 	}
 
+#ifdef ENABLE_KEYMAPPER
+	// Keymapper options
+	if (_keymapperWidget) {
+		_keymapperWidget->build();
+	}
+#endif
+
 	// Graphic options
 	if (_fullscreenCheckbox) {
 		_gfxPopUp->setSelected(0);
@@ -619,6 +630,16 @@ void OptionsDialog::apply() {
 		}
 	}
 
+#ifdef ENABLE_KEYMAPPER
+	if (_keymapperWidget) {
+		bool changes = _keymapperWidget->save();
+		if (changes) {
+			Common::Keymapper *keymapper = g_system->getEventManager()->getKeymapper();
+			keymapper->reloadAllMappings();
+		}
+	}
+#endif
+
 	// Control options
 	if (_enableControlSettings) {
 		if (g_system->hasFeature(OSystem::kFeatureOnScreenControl)) {
@@ -862,6 +883,16 @@ 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) {
 	_enableGraphicSettings = enabled;
 
@@ -1032,6 +1063,12 @@ 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
 	if (g_system->hasFeature(OSystem::kFeatureShader)) {
@@ -1578,6 +1615,40 @@ void GlobalOptionsDialog::build() {
 	}
 
 	//
+	// The Keymap tab
+	//
+#ifdef ENABLE_KEYMAPPER
+	Common::KeymapArray keymaps;
+
+	Common::Keymap *primaryGlobalKeymap = g_system->getEventManager()->getGlobalKeymap();
+	if (primaryGlobalKeymap && !primaryGlobalKeymap->getActions().empty()) {
+		keymaps.push_back(primaryGlobalKeymap);
+	}
+
+	Common::Keymap *platformGlobalKeymap = g_system->getGlobalKeymap();
+	if (platformGlobalKeymap && !platformGlobalKeymap->getActions().empty()) {
+		keymaps.push_back(platformGlobalKeymap);
+	}
+
+	Common::Keymap *guiKeymap = g_gui.getKeymap();
+	if (guiKeymap && !guiKeymap->getActions().empty()) {
+		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);
+	}
+#endif
+
+	//
 	// 2) The audio tab
 	//
 	tab->addTab(_("Audio"), "GlobalOptions_Audio");
diff --git a/gui/options.h b/gui/options.h
index ba90d92..075f8ff 100644
--- a/gui/options.h
+++ b/gui/options.h
@@ -41,6 +41,10 @@
 #include "backends/cloud/storage.h"
 #endif
 
+namespace Common {
+class RemapWidget;
+}
+
 namespace GUI {
 class LauncherDialog;
 
@@ -70,6 +74,8 @@ public:
 	virtual void apply();
 	void close() override;
 	void handleCommand(CommandSender *sender, uint32 cmd, uint32 data) override;
+	void handleTickle() override;
+
 	const Common::String& getDomain() const { return _domain; }
 
 	void reflowLayout() override;
@@ -88,6 +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 addGraphicControls(GuiObject *boss, const Common::String &prefix);
 	void addShaderControls(GuiObject *boss, const Common::String &prefix);
 	void addAudioControls(GuiObject *boss, const Common::String &prefix);
@@ -135,6 +142,11 @@ private:
 	StaticTextWidget *_joystickDeadzoneLabel;
 
 	//
+	// KeyMapper controls
+	//
+	Common::RemapWidget *_keymapperWidget;
+
+	//
 	// Graphics controls
 	//
 	bool _enableGraphicSettings;
diff --git a/gui/themes/default.inc b/gui/themes/default.inc
index 8f568c6..8972e70 100644
--- a/gui/themes/default.inc
+++ b/gui/themes/default.inc
@@ -1160,6 +1160,11 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
 "</layout>"
 "</layout>"
 "</dialog>"
+"<dialog name='GlobalOptions_KeyMapper' overlays='Dialog.GlobalOptions.TabWidget'>"
+"<layout type='vertical' padding='0,0,0,0'>"
+"<widget name='Container'/>"
+"</layout>"
+"</dialog>"
 "<dialog name='GlobalOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'>"
 "<layout type='vertical' padding='0,0,0,0'>"
 "<widget name='Container'/>"
@@ -1834,6 +1839,11 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
 "</layout>"
 "</layout>"
 "</dialog>"
+"<dialog name='GameOptions_KeyMapper' overlays='Dialog.GameOptions.TabWidget'>"
+"<layout type='vertical' padding='0,0,0,0'>"
+"<widget name='Container'/>"
+"</layout>"
+"</dialog>"
 "<dialog name='GameOptions_Graphics' overlays='Dialog.GameOptions.TabWidget'>"
 "<layout type='vertical' padding='0,0,0,0'>"
 "<widget name='Container'/>"
@@ -2535,29 +2545,6 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
 "</layout>"
 "</layout>"
 "</dialog>"
-"<dialog name='KeyMapper' overlays='screen_center' shading='dim'>"
-"<layout type='vertical' padding='8,8,8,8' spacing='10' align='center'>"
-"<layout type='horizontal' padding='8,8,8,8' spacing='10' align='center'>"
-"<widget name='PopupDesc' "
-"type='OptionsLabel' "
-"/>"
-"<widget name='Popup' "
-"type='PopUp' "
-"width='400' "
-"height='Globals.Line.Height' "
-"/>"
-"</layout>"
-"<widget name='KeymapArea' "
-"width='600' "
-"height='280' "
-"/>"
-"<layout type='horizontal' padding='8,8,8,8' align='center'>"
-"<widget name='Close' "
-"type='Button' "
-"/>"
-"</layout>"
-"</layout>"
-"</dialog>"
 "<dialog name='Predictive' overlays='screen_center'>"
 "<layout type='vertical' padding='5,5,5,5' align='center'>"
 "<widget name='Headline' "
@@ -2918,6 +2905,11 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
 "</layout>"
 "</layout>"
 "</dialog>"
+"<dialog name='GlobalOptions_KeyMapper' overlays='Dialog.GlobalOptions.TabWidget'>"
+"<layout type='vertical' padding='0,0,0,0'>"
+"<widget name='Container'/>"
+"</layout>"
+"</dialog>"
 "<dialog name='GlobalOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'>"
 "<layout type='vertical' padding='0,0,0,0'>"
 "<widget name='Container'/>"
@@ -3597,6 +3589,11 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
 "</layout>"
 "</layout>"
 "</dialog>"
+"<dialog name='GameOptions_KeyMapper' overlays='Dialog.GameOptions.TabWidget'>"
+"<layout type='vertical' padding='0,0,0,0'>"
+"<widget name='Container'/>"
+"</layout>"
+"</dialog>"
 "<dialog name='GameOptions_Graphics' overlays='Dialog.GameOptions.TabWidget'>"
 "<layout type='vertical' padding='0,0,0,0'>"
 "<widget name='Container'/>"
@@ -4267,29 +4264,6 @@ const char *defaultXML1 = "<?xml version = '1.0'?>"
 "</layout>"
 "</layout>"
 "</dialog>"
-"<dialog name='KeyMapper' overlays='screen_center' shading='dim'>"
-"<layout type='vertical' padding='8,8,8,8' spacing='10' align='center'>"
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' align='center'>"
-"<widget name='PopupDesc' "
-"type='OptionsLabel' "
-"/>"
-"<widget name='Popup' "
-"type='PopUp' "
-"width='150' "
-"height='Globals.Line.Height' "
-"/>"
-"</layout>"
-"<widget name='KeymapArea' "
-"width='300' "
-"height='120' "
-"/>"
-"<layout type='horizontal' padding='8,8,8,8' align='center'>"
-"<widget name='Close' "
-"type='Button' "
-"/>"
-"</layout>"
-"</layout>"
-"</dialog>"
 "<dialog name='Predictive' overlays='screen_center'>"
 "<layout type='vertical' padding='1,1,1,1' align='center'>"
 "<widget name='Headline' "
diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip
index 233e750..662f4eb 100644
Binary files a/gui/themes/scummclassic.zip and b/gui/themes/scummclassic.zip differ
diff --git a/gui/themes/scummclassic/THEMERC b/gui/themes/scummclassic/THEMERC
index 4aec101..b1548e4 100644
--- a/gui/themes/scummclassic/THEMERC
+++ b/gui/themes/scummclassic/THEMERC
@@ -1 +1 @@
-[SCUMMVM_STX0.8.31:ScummVM Classic Theme:No Author]
+[SCUMMVM_STX0.8.32:ScummVM Classic Theme:No Author]
diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx
index 8c4a44e..a138a70 100644
--- a/gui/themes/scummclassic/classic_layout.stx
+++ b/gui/themes/scummclassic/classic_layout.stx
@@ -285,6 +285,12 @@
 		</layout>
 	</dialog>
 
+	<dialog name = 'GlobalOptions_KeyMapper' overlays = 'Dialog.GlobalOptions.TabWidget'>
+		<layout type = 'vertical' padding = '0, 0, 0, 0'>
+			<widget name = 'Container'/>
+		</layout>
+	</dialog>
+
 	<dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
@@ -979,6 +985,12 @@
 		</layout>
 	</dialog>
 
+	<dialog name = 'GameOptions_KeyMapper' overlays = 'Dialog.GameOptions.TabWidget'>
+		<layout type = 'vertical' padding = '0, 0, 0, 0'>
+			<widget name = 'Container'/>
+		</layout>
+	</dialog>
+
 	<dialog name = 'GameOptions_Graphics' overlays = 'Dialog.GameOptions.TabWidget'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
@@ -1704,30 +1716,6 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'KeyMapper' overlays = 'screen_center' shading = 'dim'>
-		<layout type = 'vertical' padding = '8, 8, 8, 8' spacing = '10' align = 'center'>
-			<layout type = 'horizontal' padding = '8, 8, 8, 8' spacing = '10' align = 'center'>
-				<widget name = 'PopupDesc'
-						type = 'OptionsLabel'
-				/>
-				<widget name = 'Popup'
-						type = 'PopUp'
-						width = '400'
-						height = 'Globals.Line.Height'
-				/>
-			</layout>
-			<widget name = 'KeymapArea'
-					width = '600'
-					height = '280'
-			/>
-			<layout type = 'horizontal' padding = '8, 8, 8, 8' align = 'center'>
-				<widget name = 'Close'
-						type = 'Button'
-				/>
-			</layout>
-		</layout>
-	</dialog>
-
 	<dialog name = 'Predictive' overlays = 'screen_center'>
 		<layout type = 'vertical' padding = '5, 5, 5, 5' align = 'center'>
 			<widget name = 'Headline'
diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx
index 01934aa..ebd6c1f 100644
--- a/gui/themes/scummclassic/classic_layout_lowres.stx
+++ b/gui/themes/scummclassic/classic_layout_lowres.stx
@@ -282,6 +282,12 @@
 		</layout>
 	</dialog>
 
+	<dialog name = 'GlobalOptions_KeyMapper' overlays = 'Dialog.GlobalOptions.TabWidget'>
+		<layout type = 'vertical' padding = '0, 0, 0, 0'>
+			<widget name = 'Container'/>
+		</layout>
+	</dialog>
+
 	<dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
@@ -980,6 +986,12 @@
 		</layout>
 	</dialog>
 
+	<dialog name = 'GameOptions_KeyMapper' overlays = 'Dialog.GameOptions.TabWidget'>
+		<layout type = 'vertical' padding = '0, 0, 0, 0'>
+			<widget name = 'Container'/>
+		</layout>
+	</dialog>
+
 	<dialog name = 'GameOptions_Graphics' overlays = 'Dialog.GameOptions.TabWidget'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
@@ -1673,30 +1685,6 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'KeyMapper' overlays = 'screen_center' shading = 'dim'>
-		<layout type = 'vertical' padding = '8, 8, 8, 8' spacing = '10' align = 'center'>
-			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' align = 'center'>
-				<widget name = 'PopupDesc'
-						type = 'OptionsLabel'
-				/>
-				<widget name = 'Popup'
-						type = 'PopUp'
-						width = '150'
-						height = 'Globals.Line.Height'
-				/>
-			</layout>
-			<widget name = 'KeymapArea'
-					width = '300'
-					height = '120'
-			/>
-			<layout type = 'horizontal' padding = '8, 8, 8, 8' align = 'center'>
-				<widget name = 'Close'
-						type = 'Button'
-				/>
-			</layout>
-		</layout>
-	</dialog>
-
 	<dialog name = 'Predictive' overlays = 'screen_center'>
 		<layout type = 'vertical' padding = '1, 1, 1, 1' align = 'center'>
 			<widget name = 'Headline'
diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index fbaf621..18d5750 100644
Binary files a/gui/themes/scummmodern.zip and b/gui/themes/scummmodern.zip differ
diff --git a/gui/themes/scummmodern/THEMERC b/gui/themes/scummmodern/THEMERC
index 8051170..f599ce7 100644
--- a/gui/themes/scummmodern/THEMERC
+++ b/gui/themes/scummmodern/THEMERC
@@ -1 +1 @@
-[SCUMMVM_STX0.8.31:ScummVM Modern Theme:No Author]
+[SCUMMVM_STX0.8.32:ScummVM Modern Theme:No Author]
diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx
index a55530e..c2b8938 100644
--- a/gui/themes/scummmodern/scummmodern_layout.stx
+++ b/gui/themes/scummmodern/scummmodern_layout.stx
@@ -299,6 +299,12 @@
 		</layout>
 	</dialog>
 
+	<dialog name = 'GlobalOptions_KeyMapper' overlays = 'Dialog.GlobalOptions.TabWidget'>
+		<layout type = 'vertical' padding = '0, 0, 0, 0'>
+			<widget name = 'Container'/>
+		</layout>
+	</dialog>
+
 	<dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
@@ -992,6 +998,12 @@
 		</layout>
 	</dialog>
 
+	<dialog name = 'GameOptions_KeyMapper' overlays = 'Dialog.GameOptions.TabWidget'>
+		<layout type = 'vertical' padding = '0, 0, 0, 0'>
+			<widget name = 'Container'/>
+		</layout>
+	</dialog>
+
 	<dialog name = 'GameOptions_Graphics' overlays = 'Dialog.GameOptions.TabWidget'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
@@ -1718,30 +1730,6 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'KeyMapper' overlays = 'screen_center' shading = 'dim'>
-		<layout type = 'vertical' padding = '8, 8, 8, 8' spacing = '10' align = 'center'>
-			<layout type = 'horizontal' padding = '8, 8, 8, 8' spacing = '10' align = 'center'>
-				<widget name = 'PopupDesc'
-						type = 'OptionsLabel'
-				/>
-				<widget name = 'Popup'
-						type = 'PopUp'
-						width = '400'
-						height = 'Globals.Line.Height'
-				/>
-			</layout>
-			<widget name = 'KeymapArea'
-					width = '600'
-					height = '280'
-			/>
-			<layout type = 'horizontal' padding = '8, 8, 8, 8' align = 'center'>
-				<widget name = 'Close'
-						type = 'Button'
-				/>
-			</layout>
-		</layout>
-	</dialog>
-
 	<dialog name = 'Predictive' overlays = 'screen_center'>
 		<layout type = 'vertical' padding = '5, 5, 5, 5' align = 'center'>
 			<widget name = 'Headline'
@@ -1860,4 +1848,5 @@
 			</layout>
 		</layout>
 	</dialog>
+
 </layout_info>
diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
index c61f2ef..4bd8a23 100644
--- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx
+++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
@@ -243,7 +243,7 @@
 			</layout>
 		</layout>
 	</dialog>
-	
+
 	<dialog name = 'GlobalOptions_Control' overlays = 'Dialog.GlobalOptions.TabWidget'>
 		<layout type = 'vertical' padding = '16, 16, 16, 16' spacing = '8'>
 			<widget name = 'grOnScreenCheckbox'
@@ -280,6 +280,12 @@
 		</layout>
 	</dialog>
 
+	<dialog name = 'GlobalOptions_KeyMapper' overlays = 'Dialog.GlobalOptions.TabWidget'>
+		<layout type = 'vertical' padding = '0, 0, 0, 0'>
+			<widget name = 'Container'/>
+		</layout>
+	</dialog>
+
 	<dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
@@ -979,6 +985,12 @@
 		</layout>
 	</dialog>
 
+	<dialog name = 'GameOptions_KeyMapper' overlays = 'Dialog.GameOptions.TabWidget'>
+		<layout type = 'vertical' padding = '0, 0, 0, 0'>
+			<widget name = 'Container'/>
+		</layout>
+	</dialog>
+
 	<dialog name = 'GameOptions_Graphics' overlays = 'Dialog.GameOptions.TabWidget'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
@@ -1692,29 +1704,7 @@
 			</layout>
 		</layout>
 	</dialog>
-	<dialog name = 'KeyMapper' overlays = 'screen_center' shading = 'dim'>
-		<layout type = 'vertical' padding = '8, 8, 8, 8' spacing = '10' align = 'center'>
-			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' align = 'center'>
-				<widget name = 'PopupDesc'
-						type = 'OptionsLabel'
-				/>
-				<widget name = 'Popup'
-						type = 'PopUp'
-						width = '150'
-						height = 'Globals.Line.Height'
-				/>
-			</layout>
-			<widget name = 'KeymapArea'
-					width = '300'
-					height = '120'
-			/>
-			<layout type = 'horizontal' padding = '8, 8, 8, 8' align = 'center'>
-				<widget name = 'Close'
-						type = 'Button'
-				/>
-			</layout>
-		</layout>
-	</dialog>
+
 	<dialog name = 'Predictive' overlays = 'screen_center'>
 		<layout type = 'vertical' align = 'center'>
 			<widget name = 'Headline'
diff --git a/gui/themes/scummremastered.zip b/gui/themes/scummremastered.zip
index ffe5eed..c3c64a9 100644
Binary files a/gui/themes/scummremastered.zip and b/gui/themes/scummremastered.zip differ
diff --git a/gui/themes/scummremastered/THEMERC b/gui/themes/scummremastered/THEMERC
index 3b6a6d4..356de74 100644
--- a/gui/themes/scummremastered/THEMERC
+++ b/gui/themes/scummremastered/THEMERC
@@ -1 +1 @@
-[SCUMMVM_STX0.8.31:ScummVM Modern Theme Remastered:No Author]
+[SCUMMVM_STX0.8.32:ScummVM Modern Theme Remastered:No Author]
diff --git a/gui/themes/scummremastered/remastered_layout.stx b/gui/themes/scummremastered/remastered_layout.stx
index 2281c06..ba92d91 100644
--- a/gui/themes/scummremastered/remastered_layout.stx
+++ b/gui/themes/scummremastered/remastered_layout.stx
@@ -299,6 +299,12 @@
 		</layout>
 	</dialog>
 
+	<dialog name = 'GlobalOptions_KeyMapper' overlays = 'Dialog.GlobalOptions.TabWidget'>
+		<layout type = 'vertical' padding = '0, 0, 0, 0'>
+			<widget name = 'Container'/>
+		</layout>
+	</dialog>
+
 	<dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
@@ -992,6 +998,12 @@
 		</layout>
 	</dialog>
 
+	<dialog name = 'GameOptions_KeyMapper' overlays = 'Dialog.GameOptions.TabWidget'>
+		<layout type = 'vertical' padding = '0, 0, 0, 0'>
+			<widget name = 'Container'/>
+		</layout>
+	</dialog>
+
 	<dialog name = 'GameOptions_Graphics' overlays = 'Dialog.GameOptions.TabWidget'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
@@ -1718,30 +1730,6 @@
 		</layout>
 	</dialog>
 
-	<dialog name = 'KeyMapper' overlays = 'screen_center' shading = 'dim'>
-		<layout type = 'vertical' padding = '8, 8, 8, 8' spacing = '10' align = 'center'>
-			<layout type = 'horizontal' padding = '8, 8, 8, 8' spacing = '10' align = 'center'>
-				<widget name = 'PopupDesc'
-						type = 'OptionsLabel'
-				/>
-				<widget name = 'Popup'
-						type = 'PopUp'
-						width = '400'
-						height = 'Globals.Line.Height'
-				/>
-			</layout>
-			<widget name = 'KeymapArea'
-					width = '600'
-					height = '280'
-			/>
-			<layout type = 'horizontal' padding = '8, 8, 8, 8' align = 'center'>
-				<widget name = 'Close'
-						type = 'Button'
-				/>
-			</layout>
-		</layout>
-	</dialog>
-
 	<dialog name = 'Predictive' overlays = 'screen_center'>
 		<layout type = 'vertical' padding = '5, 5, 5, 5' align = 'center'>
 			<widget name = 'Headline'
diff --git a/gui/themes/scummremastered/remastered_layout_lowres.stx b/gui/themes/scummremastered/remastered_layout_lowres.stx
index a2c2b61..818e725 100644
--- a/gui/themes/scummremastered/remastered_layout_lowres.stx
+++ b/gui/themes/scummremastered/remastered_layout_lowres.stx
@@ -280,6 +280,12 @@
 		</layout>
 	</dialog>
 
+	<dialog name = 'GlobalOptions_KeyMapper' overlays = 'Dialog.GlobalOptions.TabWidget'>
+		<layout type = 'vertical' padding = '0, 0, 0, 0'>
+			<widget name = 'Container'/>
+		</layout>
+	</dialog>
+
 	<dialog name = 'GlobalOptions_Graphics' overlays = 'Dialog.GlobalOptions.TabWidget'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
@@ -979,6 +985,12 @@
 		</layout>
 	</dialog>
 
+	<dialog name = 'GameOptions_KeyMapper' overlays = 'Dialog.GameOptions.TabWidget'>
+		<layout type = 'vertical' padding = '0, 0, 0, 0'>
+			<widget name = 'Container'/>
+		</layout>
+	</dialog>
+
 	<dialog name = 'GameOptions_Graphics' overlays = 'Dialog.GameOptions.TabWidget'>
 		<layout type = 'vertical' padding = '0, 0, 0, 0'>
 			<widget name = 'Container'/>
@@ -1692,27 +1704,7 @@
 			</layout>
 		</layout>
 	</dialog>
-	<dialog name = 'KeyMapper' overlays = 'screen_center' shading = 'dim'>
-		<layout type = 'vertical' padding = '8, 8, 8, 8' spacing = '10' align = 'center'>
-			<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' align = 'center'>
-				<widget name = 'PopupDesc'
-						type = 'OptionsLabel'
-				/>
-				<widget name = 'Popup'
-						type = 'PopUp'
-						width = '150'
-						height = 'Globals.Line.Height'
-				/>
-			</layout>
-			<widget name = 'KeymapArea'
-					width = '300'
-					height = '120'
-			/>
-			<widget name = 'Close'
-					type = 'Button'
-			/>
-		</layout>
-	</dialog>
+
 	<dialog name = 'Predictive' overlays = 'screen_center'>
 		<layout type = 'vertical' align = 'center'>
 			<widget name = 'Headline'




More information about the Scummvm-git-logs mailing list