[Scummvm-git-logs] scummvm branch-2-6 -> a125b0e3f15cf3b61691de329198e4780bc1644d

lephilousophe noreply at scummvm.org
Fri Jun 17 19:36:09 UTC 2022


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

Summary:
ad5993d24f ANDROID: Let user customize its preferred touch modes
27de1f1145 ANDROID: Merge touch mode and toggle keyboard buttons
a125b0e3f1 DOCS: Update Android docs to match new touch controls settings


Commit: ad5993d24f95cfa07660781cdd685ee891e4905c
    https://github.com/scummvm/scummvm/commit/ad5993d24f95cfa07660781cdd685ee891e4905c
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-06-17T21:35:34+02:00

Commit Message:
ANDROID: Let user customize its preferred touch modes

There are 3 settings: in menus, in 2D games, in 3D games

Changed paths:
  A dists/android/res/drawable/ic_action_touchpad.xml
    backends/graphics/android/android-graphics.cpp
    backends/graphics/android/android-graphics.h
    backends/graphics3d/android/android-graphics3d.cpp
    backends/graphics3d/android/android-graphics3d.h
    backends/platform/android/android.cpp
    backends/platform/android/android.h
    backends/platform/android/events.cpp
    backends/platform/android/jni-android.cpp
    backends/platform/android/jni-android.h
    backends/platform/android/options.cpp
    backends/platform/android/org/scummvm/scummvm/ScummVM.java
    backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
    backends/platform/android/org/scummvm/scummvm/ScummVMEventsBase.java


diff --git a/backends/graphics/android/android-graphics.cpp b/backends/graphics/android/android-graphics.cpp
index 410dd94f182..f2e22de5543 100644
--- a/backends/graphics/android/android-graphics.cpp
+++ b/backends/graphics/android/android-graphics.cpp
@@ -66,7 +66,8 @@ static void loadBuiltinTexture(JNI::BitmapResources resource, OpenGL::Surface *s
 // AndroidGraphicsManager
 //
 AndroidGraphicsManager::AndroidGraphicsManager() :
-	_touchcontrols(nullptr) {
+	_touchcontrols(nullptr),
+	_old_touch_mode(OSystem_Android::TOUCH_MODE_TOUCHPAD) {
 	ENTER();
 
 	// Initialize our OpenGL ES context.
@@ -76,8 +77,8 @@ AndroidGraphicsManager::AndroidGraphicsManager() :
 	loadBuiltinTexture(JNI::BitmapResources::TOUCH_ARROWS_BITMAP, _touchcontrols);
 	_touchcontrols->updateGLTexture();
 
-	// In 2D we always fallback to standard 2D mode
-	JNI::setTouch3DMode(false);
+	// not in 3D, not in overlay
+	dynamic_cast<OSystem_Android *>(g_system)->applyTouchSettings(false, false);
 }
 
 AndroidGraphicsManager::~AndroidGraphicsManager() {
@@ -150,23 +151,13 @@ void AndroidGraphicsManager::displayMessageOnOSD(const Common::U32String &msg) {
 	JNI::displayMessageOnOSD(msg);
 }
 
-bool AndroidGraphicsManager::showMouse(bool visible) {
-	bool last = OpenGL::OpenGLGraphicsManager::showMouse(visible);
-
-	if (visible && last != visible) {
-		// We just displayed a mouse cursor, disable the 3D mode if user enabled it
-		JNI::setTouch3DMode(false);
-	}
-
-	return last;
-}
-
 void AndroidGraphicsManager::showOverlay() {
 	if (_overlayVisible)
 		return;
 
-	_old_touch_3d_mode = JNI::getTouch3DMode();
-	JNI::setTouch3DMode(false);
+	_old_touch_mode = JNI::getTouchMode();
+	// not in 3D, in overlay
+	dynamic_cast<OSystem_Android *>(g_system)->applyTouchSettings(false, true);
 
 	OpenGL::OpenGLGraphicsManager::showOverlay();
 }
@@ -175,7 +166,8 @@ void AndroidGraphicsManager::hideOverlay() {
 	if (!_overlayVisible)
 		return;
 
-	JNI::setTouch3DMode(_old_touch_3d_mode);
+	// Restore touch mode active before overlay was shown
+	JNI::setTouchMode(_old_touch_mode);
 
 	OpenGL::OpenGLGraphicsManager::hideOverlay();
 }
diff --git a/backends/graphics/android/android-graphics.h b/backends/graphics/android/android-graphics.h
index beb0a58ae58..74a3c6311e4 100644
--- a/backends/graphics/android/android-graphics.h
+++ b/backends/graphics/android/android-graphics.h
@@ -89,7 +89,6 @@ public:
 
 protected:
 	void setSystemMousePosition(const int x, const int y) override {}
-	bool showMouse(bool visible) override;
 
 	void showOverlay() override;
 	void hideOverlay() override;
@@ -103,7 +102,7 @@ protected:
 
 private:
 	OpenGL::Surface *_touchcontrols;
-	bool _old_touch_3d_mode;
+	int _old_touch_mode;
 };
 
 #endif
diff --git a/backends/graphics3d/android/android-graphics3d.cpp b/backends/graphics3d/android/android-graphics3d.cpp
index ea78e61b755..9203401ea51 100644
--- a/backends/graphics3d/android/android-graphics3d.cpp
+++ b/backends/graphics3d/android/android-graphics3d.cpp
@@ -93,7 +93,7 @@ AndroidGraphics3dManager::AndroidGraphics3dManager() :
 	_mouse_dont_scale(false),
 	_show_mouse(false),
 	_touchcontrols_texture(nullptr),
-	_old_touch_3d_mode(false) {
+	_old_touch_mode(OSystem_Android::TOUCH_MODE_TOUCHPAD) {
 
 	if (JNI::egl_bits_per_pixel == 16) {
 		// We default to RGB565 and RGBA5551 which is closest to what we setup in Java side
@@ -113,7 +113,9 @@ AndroidGraphics3dManager::AndroidGraphics3dManager() :
 	_touchcontrols_texture = loadBuiltinTexture(JNI::BitmapResources::TOUCH_ARROWS_BITMAP);
 
 	initSurface();
-	JNI::setTouch3DMode(true);
+
+	// in 3D, not in overlay
+	dynamic_cast<OSystem_Android *>(g_system)->applyTouchSettings(true, false);
 }
 
 AndroidGraphics3dManager::~AndroidGraphics3dManager() {
@@ -124,8 +126,6 @@ AndroidGraphics3dManager::~AndroidGraphics3dManager() {
 	glBindRenderbuffer(GL_RENDERBUFFER, 0);
 	glUseProgram(0);
 
-	JNI::setTouch3DMode(false);
-
 	deinitSurface();
 
 	delete _frame_buffer;
@@ -457,8 +457,9 @@ void AndroidGraphics3dManager::showOverlay() {
 		return;
 	}
 
-	_old_touch_3d_mode = JNI::getTouch3DMode();
-	JNI::setTouch3DMode(false);
+	_old_touch_mode = JNI::getTouchMode();
+	// in 3D, in overlay
+	dynamic_cast<OSystem_Android *>(g_system)->applyTouchSettings(true, true);
 
 	_show_overlay = true;
 	_force_redraw = true;
@@ -504,7 +505,8 @@ void AndroidGraphics3dManager::hideOverlay() {
 
 	_overlay_background->release();
 
-	JNI::setTouch3DMode(_old_touch_3d_mode);
+	// Restore touch mode active before overlay was shown
+	JNI::setTouchMode(_old_touch_mode);
 
 	warpMouse(_game_texture->width() / 2, _game_texture->height() / 2);
 
diff --git a/backends/graphics3d/android/android-graphics3d.h b/backends/graphics3d/android/android-graphics3d.h
index 0e1d3b942f1..846f0b1a5d3 100644
--- a/backends/graphics3d/android/android-graphics3d.h
+++ b/backends/graphics3d/android/android-graphics3d.h
@@ -183,7 +183,7 @@ private:
 
 	// Touch controls layer
 	GLESTexture *_touchcontrols_texture;
-	bool _old_touch_3d_mode;
+	int _old_touch_mode;
 };
 
 #endif
diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index 007cb5c7b67..a8532969706 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -139,7 +139,7 @@ OSystem_Android::OSystem_Android(int audio_sample_rate, int audio_buffer_size) :
 	_eventScaleX(100),
 	_eventScaleY(100),
 	// TODO put these values in some option dlg?
-	_touchpad_mode(true),
+	_touch_mode(TOUCH_MODE_TOUCHPAD),
 	_touchpad_scale(66),
 	_dpad_scale(4),
 //	_fingersDown(0),
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
index 35a5a66cebc..4b83e05ebd0 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -121,6 +121,13 @@ private:
 	Common::String getSystemProperty(const char *name) const;
 
 public:
+	enum {
+		TOUCH_MODE_TOUCHPAD = 0,
+		TOUCH_MODE_MOUSE = 1,
+		TOUCH_MODE_GAMEPAD = 2,
+		TOUCH_MODE_MAX = 3
+	};
+
 	OSystem_Android(int audio_sample_rate, int audio_buffer_size);
 	virtual ~OSystem_Android();
 
@@ -136,6 +143,8 @@ public:
 	void pushEvent(const Common::Event &event1, const Common::Event &event2);
 
 	TouchControls &getTouchControls() { return _touchControls; }
+	void applyTouchSettings(bool _3dMode, bool overlayShown);
+	void setupTouchMode(int oldValue, int newValue);
 
 private:
 	Common::Queue<Common::Event> _event_queue;
@@ -146,7 +155,7 @@ private:
 	Common::Point _touch_pt_down, _touch_pt_scroll, _touch_pt_dt, _touch_pt_multi;
 	int _eventScaleX;
 	int _eventScaleY;
-	bool _touchpad_mode;
+	int _touch_mode;
 	int _touchpad_scale;
 	int _trackball_scale;
 	int _dpad_scale;
diff --git a/backends/platform/android/events.cpp b/backends/platform/android/events.cpp
index b26f7fd8174..bd4351886cb 100644
--- a/backends/platform/android/events.cpp
+++ b/backends/platform/android/events.cpp
@@ -618,7 +618,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
 //		LOGD("JE_SCROLL");
 		e.type = Common::EVENT_MOUSEMOVE;
 
-		if (_touchpad_mode) {
+		if (_touch_mode == TOUCH_MODE_TOUCHPAD) {
 			if (_touch_pt_scroll.x == -1 && _touch_pt_scroll.y == -1) {
 				_touch_pt_scroll.x = arg3;
 				_touch_pt_scroll.y = arg4;
@@ -647,7 +647,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
 
 		e.type = Common::EVENT_MOUSEMOVE;
 
-		if (_touchpad_mode) {
+		if (_touch_mode == TOUCH_MODE_TOUCHPAD) {
 			e.mouse = dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->getMousePosition();
 		} else {
 			e.mouse.x = arg1;
@@ -695,7 +695,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
 				_event_queue.push(_queuedEvent);
 			}
 
-			if (!_touchpad_mode) {
+			if (_touch_mode != TOUCH_MODE_TOUCHPAD) {
 				// In this case the mouse move is done in "direct mode"
 				// ie. the cursor jumps to where the tap occured
 				// so we don't have relMouse coordinates to set for the event
@@ -722,7 +722,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
 
 		e.type = Common::EVENT_MOUSEMOVE;
 
-		if (_touchpad_mode) {
+		if (_touch_mode == TOUCH_MODE_TOUCHPAD) {
 			e.mouse = dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->getMousePosition();
 		} else {
 			e.mouse.x = arg1;
@@ -753,7 +753,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
 
 				dptype = Common::EVENT_MOUSEMOVE;
 
-				if (_touchpad_mode) {
+				if (_touch_mode == TOUCH_MODE_TOUCHPAD) {
 					e.mouse.x = (arg1 - _touch_pt_dt.x) * 100 / _touchpad_scale;
 					e.mouse.y = (arg2 - _touch_pt_dt.y) * 100 / _touchpad_scale;
 					e.mouse += _touch_pt_down;
@@ -791,7 +791,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
 
 		e.type = Common::EVENT_MOUSEMOVE;
 
-		if (_touchpad_mode) {
+		if (_touch_mode == TOUCH_MODE_TOUCHPAD) {
 			e.mouse = dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->getMousePosition();
 		} else {
 			e.mouse.x = arg3;
@@ -918,7 +918,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
 				multitype = Common::EVENT_MOUSEMOVE;
 
 				// TODO TO TEST for non-touchpad mode too!
-				if (_touchpad_mode) {
+				if (_touch_mode == TOUCH_MODE_TOUCHPAD) {
 					e.mouse.x = (arg3 - _touch_pt_multi.x) * 100 / _touchpad_scale;
 					e.mouse.y = (arg4 - _touch_pt_multi.y) * 100 / _touchpad_scale;
 					e.mouse += _touch_pt_down; // TODO maybe we need another reference point???
@@ -1309,4 +1309,15 @@ void OSystem_Android::pushEvent(const Common::Event &event1, const Common::Event
 	_event_queue_lock->unlock();
 }
 
+void OSystem_Android::setupTouchMode(int oldValue, int newValue) {
+	_touch_mode = newValue;
+
+	if (newValue == TOUCH_MODE_TOUCHPAD) {
+		// Make sure we have a proper touch point if we switch to touchpad mode with finger down
+		_touch_pt_down = dynamic_cast<AndroidCommonGraphics *>(_graphicsManager)->getMousePosition();
+		_touch_pt_scroll.x = -1;
+		_touch_pt_scroll.y = -1;
+	}
+}
+
 #endif
diff --git a/backends/platform/android/jni-android.cpp b/backends/platform/android/jni-android.cpp
index 2140e881b68..de6472deda5 100644
--- a/backends/platform/android/jni-android.cpp
+++ b/backends/platform/android/jni-android.cpp
@@ -88,8 +88,8 @@ jmethodID JNI::_MID_setWindowCaption = 0;
 jmethodID JNI::_MID_showVirtualKeyboard = 0;
 jmethodID JNI::_MID_showKeyboardControl = 0;
 jmethodID JNI::_MID_getBitmapResource = 0;
-jmethodID JNI::_MID_setTouch3DMode = 0;
-jmethodID JNI::_MID_getTouch3DMode = 0;
+jmethodID JNI::_MID_setTouchMode = 0;
+jmethodID JNI::_MID_getTouchMode = 0;
 jmethodID JNI::_MID_showSAFRevokePermsControl = 0;
 jmethodID JNI::_MID_getSysArchives = 0;
 jmethodID JNI::_MID_getAllStorageLocations = 0;
@@ -126,6 +126,8 @@ const JNINativeMethod JNI::_natives[] = {
 		(void *)JNI::pushEvent },
 	{ "updateTouch", "(IIII)V",
 		(void *)JNI::updateTouch },
+	{ "setupTouchMode", "(II)V",
+		(void *)JNI::setupTouchMode },
 	{ "setPause", "(Z)V",
 		(void *)JNI::setPause },
 	{ "getNativeVersionInfo", "()Ljava/lang/String;",
@@ -455,10 +457,10 @@ Graphics::Surface *JNI::getBitmapResource(BitmapResources resource) {
 	return ret;
 }
 
-void JNI::setTouch3DMode(bool touch3DMode) {
+void JNI::setTouchMode(int touchMode) {
 	JNIEnv *env = JNI::getEnv();
 
-	env->CallVoidMethod(_jobj, _MID_setTouch3DMode, touch3DMode);
+	env->CallVoidMethod(_jobj, _MID_setTouchMode, touchMode);
 
 	if (env->ExceptionCheck()) {
 		LOGE("Error trying to set touch controls mode");
@@ -468,10 +470,10 @@ void JNI::setTouch3DMode(bool touch3DMode) {
 	}
 }
 
-bool JNI::getTouch3DMode() {
+int JNI::getTouchMode() {
 	JNIEnv *env = JNI::getEnv();
 
-	bool enabled = env->CallBooleanMethod(_jobj, _MID_getTouch3DMode);
+	int mode = env->CallIntMethod(_jobj, _MID_getTouchMode);
 
 	if (env->ExceptionCheck()) {
 		LOGE("Error trying to get touch controls status");
@@ -480,7 +482,7 @@ bool JNI::getTouch3DMode() {
 		env->ExceptionClear();
 	}
 
-	return enabled;
+	return mode;
 }
 
 void JNI::showSAFRevokePermsControl(bool enable) {
@@ -667,8 +669,8 @@ void JNI::create(JNIEnv *env, jobject self, jobject asset_manager,
 	FIND_METHOD(, showVirtualKeyboard, "(Z)V");
 	FIND_METHOD(, showKeyboardControl, "(Z)V");
 	FIND_METHOD(, getBitmapResource, "(I)Landroid/graphics/Bitmap;");
-	FIND_METHOD(, setTouch3DMode, "(Z)V");
-	FIND_METHOD(, getTouch3DMode, "()Z");
+	FIND_METHOD(, setTouchMode, "(I)V");
+	FIND_METHOD(, getTouchMode, "()I");
 	FIND_METHOD(, getSysArchives, "()[Ljava/lang/String;");
 	FIND_METHOD(, getAllStorageLocations, "()[Ljava/lang/String;");
 	FIND_METHOD(, initSurface, "()Ljavax/microedition/khronos/egl/EGLSurface;");
@@ -822,6 +824,13 @@ void JNI::updateTouch(JNIEnv *env, jobject self, int action, int ptr, int x, int
 	_system->getTouchControls().update((TouchControls::Action) action, ptr, x, y);
 }
 
+void JNI::setupTouchMode(JNIEnv *env, jobject self, jint oldValue, jint newValue) {
+	if (!_system)
+		return;
+
+	_system->setupTouchMode(oldValue, newValue);
+}
+
 void JNI::setPause(JNIEnv *env, jobject self, jboolean value) {
 	if (!_system)
 		return;
diff --git a/backends/platform/android/jni-android.h b/backends/platform/android/jni-android.h
index d3afb71f2e7..7b69e2a4211 100644
--- a/backends/platform/android/jni-android.h
+++ b/backends/platform/android/jni-android.h
@@ -77,8 +77,8 @@ public:
 	static void showVirtualKeyboard(bool enable);
 	static void showKeyboardControl(bool enable);
 	static Graphics::Surface *getBitmapResource(BitmapResources resource);
-	static void setTouch3DMode(bool touch3DMode);
-	static bool getTouch3DMode();
+	static void setTouchMode(int touchMode);
+	static int getTouchMode();
 	static void showSAFRevokePermsControl(bool enable);
 	static void addSysArchivesToSearchSet(Common::SearchSet &s, int priority);
 
@@ -126,8 +126,8 @@ private:
 	static jmethodID _MID_showVirtualKeyboard;
 	static jmethodID _MID_showKeyboardControl;
 	static jmethodID _MID_getBitmapResource;
-	static jmethodID _MID_setTouch3DMode;
-	static jmethodID _MID_getTouch3DMode;
+	static jmethodID _MID_setTouchMode;
+	static jmethodID _MID_getTouchMode;
 	static jmethodID _MID_showSAFRevokePermsControl;
 	static jmethodID _MID_getSysArchives;
 	static jmethodID _MID_getAllStorageLocations;
@@ -164,6 +164,7 @@ private:
 	static void pushEvent(JNIEnv *env, jobject self, int type, int arg1,
 							int arg2, int arg3, int arg4, int arg5, int arg6);
 	static void updateTouch(JNIEnv *env, jobject self, int action, int ptr, int x, int y);
+	static void setupTouchMode(JNIEnv *env, jobject self, jint oldValue, jint newValue);
 	static void setPause(JNIEnv *env, jobject self, jboolean value);
 
 	static jstring getNativeVersionInfo(JNIEnv *env, jobject self);
diff --git a/backends/platform/android/options.cpp b/backends/platform/android/options.cpp
index aff4b02dec9..8edb0e6e094 100644
--- a/backends/platform/android/options.cpp
+++ b/backends/platform/android/options.cpp
@@ -39,8 +39,10 @@
 #include "backends/platform/android/android.h"
 #include "backends/platform/android/jni-android.h"
 
+#include "gui/gui-manager.h"
 #include "gui/ThemeEval.h"
 #include "gui/widget.h"
+#include "gui/widgets/popup.h"
 
 #include "common/translation.h"
 
@@ -60,17 +62,67 @@ private:
 	void defineLayout(GUI::ThemeEval &layouts, const Common::String &layoutName, const Common::String &overlayedLayout) const override;
 
 	GUI::CheckboxWidget *_onscreenCheckbox;
-	GUI::CheckboxWidget *_touchpadCheckbox;
+	GUI::StaticTextWidget *_preferredTouchModeDesc;
+	GUI::StaticTextWidget *_preferredTMMenusDesc;
+	GUI::PopUpWidget *_preferredTMMenusPopUp;
+	GUI::StaticTextWidget *_preferredTM2DGamesDesc;
+	GUI::PopUpWidget *_preferredTM2DGamesPopUp;
+	GUI::StaticTextWidget *_preferredTM3DGamesDesc;
+	GUI::PopUpWidget *_preferredTM3DGamesPopUp;
 	GUI::CheckboxWidget *_onscreenSAFRevokeCheckbox;
 
 	bool _enabled;
+
+
+	uint32 loadTouchMode(const Common::String &setting, bool acceptDefault, uint32 defaultValue);
+	void saveTouchMode(const Common::String &setting, uint32 touchMode);
+};
+
+enum {
+	kTouchModeDefault = -1,
+	kTouchModeTouchpad = 0,
+	kTouchModeMouse,
+	kTouchModeGamepad,
 };
 
 AndroidOptionsWidget::AndroidOptionsWidget(GuiObject *boss, const Common::String &name, const Common::String &domain) :
 		OptionsContainerWidget(boss, name, "AndroidOptionsDialog", false, domain), _enabled(true) {
+
+	const bool inAppDomain = domain.equalsIgnoreCase(Common::ConfigManager::kApplicationDomain);;
+
 	_onscreenCheckbox = new GUI::CheckboxWidget(widgetsBoss(), "AndroidOptionsDialog.OnScreenControl", _("Show On-screen control"));
-	_touchpadCheckbox = new GUI::CheckboxWidget(widgetsBoss(), "AndroidOptionsDialog.TouchpadMode", _("Touchpad mouse mode"));
-	if (domain.equalsIgnoreCase(Common::ConfigManager::kApplicationDomain)) {
+	_preferredTouchModeDesc = new GUI::StaticTextWidget(widgetsBoss(), "AndroidOptionsDialog.PreferredTouchModeText", _("Choose the preferred touch mode:"));
+	if (inAppDomain) {
+		_preferredTMMenusDesc = new GUI::StaticTextWidget(widgetsBoss(), "AndroidOptionsDialog.TMMenusText", _("In menus"));
+		_preferredTMMenusPopUp = new GUI::PopUpWidget(widgetsBoss(), "AndroidOptionsDialog.TMMenus");
+		_preferredTMMenusPopUp->appendEntry(_("Touchpad emulation"), kTouchModeTouchpad);
+		_preferredTMMenusPopUp->appendEntry(_("Direct mouse"), kTouchModeMouse); // TODO: Find a better name
+		_preferredTMMenusPopUp->appendEntry(_("Gamepad emulation"), kTouchModeGamepad);
+	} else {
+		_preferredTMMenusDesc = nullptr;
+		_preferredTMMenusPopUp = nullptr;
+	}
+
+	_preferredTM2DGamesDesc = new GUI::StaticTextWidget(widgetsBoss(), "AndroidOptionsDialog.TM2DGamesText", _("In 2D games"));
+	_preferredTM2DGamesPopUp = new GUI::PopUpWidget(widgetsBoss(), "AndroidOptionsDialog.TM2DGames");
+	_preferredTM3DGamesDesc = new GUI::StaticTextWidget(widgetsBoss(), "AndroidOptionsDialog.TM3DGamesText", _("In 3D games"));
+	_preferredTM3DGamesPopUp = new GUI::PopUpWidget(widgetsBoss(), "AndroidOptionsDialog.TM3DGames");
+
+	if (!inAppDomain) {
+		_preferredTM2DGamesPopUp->appendEntry(_("<default>"), kTouchModeDefault);
+		_preferredTM3DGamesPopUp->appendEntry(_("<default>"), kTouchModeDefault);
+	}
+
+	_preferredTM2DGamesPopUp->appendEntry(_("Touchpad emulation"), kTouchModeTouchpad);
+	_preferredTM3DGamesPopUp->appendEntry(_("Touchpad emulation"), kTouchModeTouchpad);
+
+	_preferredTM2DGamesPopUp->appendEntry(_("Direct mouse"), kTouchModeMouse); // TODO: Find a better name
+	_preferredTM3DGamesPopUp->appendEntry(_("Direct mouse"), kTouchModeMouse);
+
+	_preferredTM2DGamesPopUp->appendEntry(_("Gamepad emulation"), kTouchModeGamepad);
+	_preferredTM3DGamesPopUp->appendEntry(_("Gamepad emulation"), kTouchModeGamepad);
+
+	if (inAppDomain) {
 		// Only show this checkbox in Options (via Options... in the launcher), and not at game domain level (via Edit Game...)
 		// I18N: Show a button to revoke Storage Access Framework permissions for Android
 		_onscreenSAFRevokeCheckbox = new GUI::CheckboxWidget(widgetsBoss(), "AndroidOptionsDialog.SAFRevokePermsControl", _("Show SAF revoke permissions overlay button"));
@@ -81,37 +133,115 @@ AndroidOptionsWidget::~AndroidOptionsWidget() {
 }
 
 void AndroidOptionsWidget::defineLayout(GUI::ThemeEval &layouts, const Common::String &layoutName, const Common::String &overlayedLayout) const {
+	const bool inAppDomain = _domain.equalsIgnoreCase(Common::ConfigManager::kApplicationDomain);;
+
 	layouts.addDialog(layoutName, overlayedLayout)
 	        .addLayout(GUI::ThemeLayout::kLayoutVertical)
 	            .addPadding(0, 0, 0, 0)
 	            .addWidget("OnScreenControl", "Checkbox")
-	            .addWidget("TouchpadMode", "Checkbox");
-	if (_domain.equalsIgnoreCase(Common::ConfigManager::kApplicationDomain)) {
+				.addWidget("PreferredTouchModeText", "", -1, layouts.getVar("Globals.Line.Height"));
+
+	if (inAppDomain) {
+		layouts.addLayout(GUI::ThemeLayout::kLayoutHorizontal)
+			.addPadding(0, 0, 0, 0)
+			.addWidget("TMMenusText", "OptionsLabel")
+			.addWidget("TMMenus", "PopUp")
+		.closeLayout();
+	}
+	layouts.addLayout(GUI::ThemeLayout::kLayoutHorizontal)
+			.addPadding(0, 0, 0, 0)
+			.addWidget("TM2DGamesText", "OptionsLabel")
+			.addWidget("TM2DGames", "PopUp")
+		.closeLayout()
+		.addLayout(GUI::ThemeLayout::kLayoutHorizontal)
+			.addPadding(0, 0, 0, 0)
+			.addWidget("TM3DGamesText", "OptionsLabel")
+			.addWidget("TM3DGames", "PopUp")
+		.closeLayout();
+	if (inAppDomain) {
 		layouts.addWidget("SAFRevokePermsControl", "Checkbox");
 	}
 	layouts.closeLayout()
 	    .closeDialog();
 }
 
+uint32 AndroidOptionsWidget::loadTouchMode(const Common::String &setting, bool acceptDefault, uint32 defaultValue) {
+	if (!acceptDefault || ConfMan.hasKey(setting, _domain)) {
+		Common::String preferredTouchMode = ConfMan.get(setting, _domain);
+		if (preferredTouchMode == "mouse") {
+			return kTouchModeMouse;
+		} else if (preferredTouchMode == "gamepad") {
+			return kTouchModeGamepad;
+		} else if (preferredTouchMode == "touchpad") {
+			return kTouchModeTouchpad;
+		} else {
+			return defaultValue;
+		}
+	} else {
+		return kTouchModeDefault;
+	}
+}
+
 void AndroidOptionsWidget::load() {
+	const bool inAppDomain = _domain.equalsIgnoreCase(Common::ConfigManager::kApplicationDomain);
+
 	_onscreenCheckbox->setState(ConfMan.getBool("onscreen_control", _domain));
-	_touchpadCheckbox->setState(ConfMan.getBool("touchpad_mouse_mode", _domain));
-	if (_domain.equalsIgnoreCase(Common::ConfigManager::kApplicationDomain)) {
+
+	// When in application domain, we don't have default entry so we must have a value
+	if (inAppDomain) {
+		_preferredTMMenusPopUp->setSelectedTag(loadTouchMode("touch_mode_menus", !inAppDomain, kTouchModeMouse));
+	}
+	_preferredTM2DGamesPopUp->setSelectedTag(loadTouchMode("touch_mode_2d_games", !inAppDomain, kTouchModeTouchpad));
+	_preferredTM3DGamesPopUp->setSelectedTag(loadTouchMode("touch_mode_3d_games", !inAppDomain, kTouchModeGamepad));
+
+	if (inAppDomain) {
 		_onscreenSAFRevokeCheckbox->setState(ConfMan.getBool("onscreen_saf_revoke_btn", _domain));
 	}
 }
 
+void AndroidOptionsWidget::saveTouchMode(const Common::String &setting, uint32 touchMode) {
+	switch (touchMode) {
+	case kTouchModeTouchpad:
+		ConfMan.set(setting, "touchpad", _domain);
+		break;
+	case kTouchModeMouse:
+		ConfMan.set(setting, "mouse", _domain);
+		break;
+	case kTouchModeGamepad:
+		ConfMan.set(setting, "gamepad", _domain);
+		break;
+	default:
+		// default
+		ConfMan.removeKey(setting, _domain);
+		break;
+	}
+}
+
 bool AndroidOptionsWidget::save() {
+	const bool inAppDomain = _domain.equalsIgnoreCase(Common::ConfigManager::kApplicationDomain);
+
 	if (_enabled) {
 		ConfMan.setBool("onscreen_control", _onscreenCheckbox->getState(), _domain);
-		ConfMan.setBool("touchpad_mouse_mode", _touchpadCheckbox->getState(), _domain);
-		if (_domain.equalsIgnoreCase(Common::ConfigManager::kApplicationDomain)) {
+
+		if (inAppDomain) {
+			saveTouchMode("touch_mode_menus", _preferredTMMenusPopUp->getSelectedTag());
+		}
+		saveTouchMode("touch_mode_2d_games", _preferredTM2DGamesPopUp->getSelectedTag());
+		saveTouchMode("touch_mode_3d_games", _preferredTM3DGamesPopUp->getSelectedTag());
+
+		if (inAppDomain) {
 			ConfMan.setBool("onscreen_saf_revoke_btn", _onscreenSAFRevokeCheckbox->getState(), _domain);
 		}
 	} else {
 		ConfMan.removeKey("onscreen_control", _domain);
-		ConfMan.removeKey("touchpad_mouse_mode", _domain);
-		if (_domain.equalsIgnoreCase(Common::ConfigManager::kApplicationDomain)) {
+
+		if (inAppDomain) {
+			ConfMan.removeKey("touch_mode_menus", _domain);
+		}
+		ConfMan.removeKey("touch_mode_2d_games", _domain);
+		ConfMan.removeKey("touch_mode_3d_games", _domain);
+
+		if (inAppDomain) {
 			ConfMan.removeKey("onscreen_saf_revoke_btn", _domain);
 		}
 	}
@@ -121,16 +251,29 @@ bool AndroidOptionsWidget::save() {
 
 bool AndroidOptionsWidget::hasKeys() {
 	return ConfMan.hasKey("onscreen_control", _domain) ||
-	       ConfMan.hasKey("touchpad_mouse_mode", _domain) ||
+	       (_domain.equalsIgnoreCase(Common::ConfigManager::kApplicationDomain) && ConfMan.hasKey("touch_mode_menus", _domain)) ||
+	       ConfMan.hasKey("touch_mode_2d_games", _domain) ||
+	       ConfMan.hasKey("touch_mode_3d_games", _domain) ||
 	       (_domain.equalsIgnoreCase(Common::ConfigManager::kApplicationDomain) && ConfMan.hasKey("onscreen_saf_revoke_btn", _domain));
 }
 
 void AndroidOptionsWidget::setEnabled(bool e) {
+	const bool inAppDomain = _domain.equalsIgnoreCase(Common::ConfigManager::kApplicationDomain);
+
 	_enabled = e;
 
 	_onscreenCheckbox->setEnabled(e);
-	_touchpadCheckbox->setEnabled(e);
-	if (_domain.equalsIgnoreCase(Common::ConfigManager::kApplicationDomain)) {
+
+	if (inAppDomain) {
+		_preferredTMMenusDesc->setEnabled(e);
+		_preferredTMMenusPopUp->setEnabled(e);
+	}
+	_preferredTM2DGamesDesc->setEnabled(e);
+	_preferredTM2DGamesPopUp->setEnabled(e);
+	_preferredTM3DGamesDesc->setEnabled(e);
+	_preferredTM3DGamesPopUp->setEnabled(e);
+
+	if (inAppDomain) {
 		_onscreenSAFRevokeCheckbox->setEnabled(e);
 	}
 }
@@ -142,12 +285,40 @@ GUI::OptionsContainerWidget *OSystem_Android::buildBackendOptionsWidget(GUI::Gui
 
 void OSystem_Android::registerDefaultSettings(const Common::String &target) const {
 	ConfMan.registerDefault("onscreen_control", true);
-	ConfMan.registerDefault("touchpad_mouse_mode", true);
+	ConfMan.registerDefault("touch_mode_menus", "mouse");
+	ConfMan.registerDefault("touch_mode_2d_games", "touchpad");
+	ConfMan.registerDefault("touch_mode_3d_games", "gamepad");
 	ConfMan.registerDefault("onscreen_saf_revoke_btn", false);
 }
 
+void OSystem_Android::applyTouchSettings(bool _3dMode, bool overlayShown) {
+	Common::String setting;
+	int defaultMode;
+
+	if (overlayShown) {
+		setting = "touch_mode_menus";
+		defaultMode = TOUCH_MODE_MOUSE;
+	} else if (_3dMode) {
+		setting = "touch_mode_3d_games";
+		defaultMode = TOUCH_MODE_GAMEPAD;
+	} else {
+		setting = "touch_mode_2d_games";
+		defaultMode = TOUCH_MODE_TOUCHPAD;
+	}
+
+	Common::String preferredTouchMode = ConfMan.get(setting);
+	if (preferredTouchMode == "mouse") {
+		JNI::setTouchMode(TOUCH_MODE_MOUSE);
+	} else if (preferredTouchMode == "gamepad") {
+		JNI::setTouchMode(TOUCH_MODE_GAMEPAD);
+	} else if (preferredTouchMode == "touchpad") {
+		JNI::setTouchMode(TOUCH_MODE_TOUCHPAD);
+	} else {
+		JNI::setTouchMode(defaultMode);
+	}
+}
+
 void OSystem_Android::applyBackendSettings() {
 	JNI::showKeyboardControl(ConfMan.getBool("onscreen_control"));
 	JNI::showSAFRevokePermsControl(ConfMan.getBool("onscreen_saf_revoke_btn"));
-	_touchpad_mode = ConfMan.getBool("touchpad_mouse_mode");
 }
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVM.java b/backends/platform/android/org/scummvm/scummvm/ScummVM.java
index 1ff62d65f42..83b30c7f7cd 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVM.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVM.java
@@ -58,6 +58,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
 	final public native void pushEvent(int type, int arg1, int arg2, int arg3,
 										int arg4, int arg5, int arg6);
 	// Update the 3D touch controls
+	final public native void setupTouchMode(int oldValue, int newValue);
 	final public native void updateTouch(int action, int ptr, int x, int y);
 
 	final public native String getNativeVersionInfo();
@@ -74,8 +75,8 @@ public abstract class ScummVM implements SurfaceHolder.Callback, Runnable {
 	abstract protected void showVirtualKeyboard(boolean enable);
 	abstract protected void showKeyboardControl(boolean enable);
 	abstract protected Bitmap getBitmapResource(int resource);
-	abstract protected void setTouch3DMode(boolean touch3DMode);
-	abstract protected boolean getTouch3DMode();
+	abstract protected void setTouchMode(int touchMode);
+	abstract protected int getTouchMode();
 	abstract protected void showSAFRevokePermsControl(boolean enable);
 	abstract protected String[] getSysArchives();
 	abstract protected String[] getAllStorageLocations();
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index 18b537643ee..9e21ba67058 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -118,7 +118,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
 	FrameLayout _videoLayout = null;
 
 	private EditableSurfaceView _main_surface = null;
-	private ImageView _toggleGamepadBtnIcon = null;
+	private ImageView _toggleTouchModeBtnIcon = null;
 	private ImageView _toggleKeyboardBtnIcon = null;
 	private ImageView _openMenuBtnIcon = null;
 	private ImageView _revokeSafPermissionsBtnIcon = null;
@@ -570,14 +570,33 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
 	// ---------------------------------------------------------------------------------------------------------------------------
 	//
 
-	public final View.OnClickListener gamepadBtnOnClickListener = new View.OnClickListener() {
+	protected void setupTouchModeBtn(final int touchMode) {
+		int resId;
+
+		switch(touchMode) {
+		case ScummVMEventsBase.TOUCH_MODE_TOUCHPAD:
+			resId = R.drawable.ic_action_touchpad;
+			break;
+		case ScummVMEventsBase.TOUCH_MODE_MOUSE:
+			resId = R.drawable.ic_action_mouse;
+			break;
+		case ScummVMEventsBase.TOUCH_MODE_GAMEPAD:
+			resId = R.drawable.ic_action_gamepad;
+			break;
+		default:
+			throw new IllegalArgumentException("Invalid touchMode");
+		}
+
+		_toggleTouchModeBtnIcon.setImageResource(resId);
+	}
+
+	public final View.OnClickListener touchModeBtnOnClickListener = new View.OnClickListener() {
 		@Override
 		public void onClick(View v) {
 			runOnUiThread(new Runnable() {
 				public void run() {
-					boolean touch3DMode = !_events.getTouch3DMode();
-					_events.setTouch3DMode(touch3DMode);
-					_toggleGamepadBtnIcon.setImageResource(touch3DMode ? R.drawable.ic_action_mouse : R.drawable.ic_action_gamepad);
+					int newTouchMode = _events.nextTouchMode();
+					setupTouchModeBtn(newTouchMode);
 				}
 			});
 		}
@@ -739,21 +758,21 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
 		}
 
 		@Override
-		protected void setTouch3DMode(final boolean touch3DMode) {
-			if (_events.getTouch3DMode() == touch3DMode) {
+		protected void setTouchMode(final int touchMode) {
+			if (_events.getTouchMode() == touchMode) {
 				return;
 			}
 			runOnUiThread(new Runnable() {
 				public void run() {
-					_events.setTouch3DMode(touch3DMode);
-					_toggleGamepadBtnIcon.setImageResource(touch3DMode ? R.drawable.ic_action_mouse : R.drawable.ic_action_gamepad);
+					_events.setTouchMode(touchMode);
+					setupTouchModeBtn(touchMode);
 				}
 			});
 		}
 
 		@Override
-		protected boolean getTouch3DMode() {
-			return _events.getTouch3DMode();
+		protected int getTouchMode() {
+			return _events.getTouchMode();
 		}
 
 		@Override
@@ -1009,10 +1028,9 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
 		_videoLayout.addView(buttonLayout, buttonLayoutParams);
 		_videoLayout.bringChildToFront(buttonLayout);
 
-		_toggleGamepadBtnIcon = new ImageView(this);
-		_toggleGamepadBtnIcon.setImageResource(R.drawable.ic_action_gamepad);
-		buttonLayout.addView(_toggleGamepadBtnIcon, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT));
-		buttonLayout.bringChildToFront(_toggleGamepadBtnIcon);
+		_toggleTouchModeBtnIcon = new ImageView(this);
+		buttonLayout.addView(_toggleTouchModeBtnIcon, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT));
+		buttonLayout.bringChildToFront(_toggleTouchModeBtnIcon);
 
 		_toggleKeyboardBtnIcon = new ImageView(this);
 		_toggleKeyboardBtnIcon.setImageResource(R.drawable.ic_action_keyboard);
@@ -1121,9 +1139,11 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
 				_events = new ScummVMEventsBase(this, _scummvm, _mouseHelper);
 			}
 
+			setupTouchModeBtn(_events.getTouchMode());
+
 			// On screen button listener
 			//findViewById(R.id.show_keyboard).setOnClickListener(keyboardBtnOnClickListener);
-			_toggleGamepadBtnIcon.setOnClickListener(gamepadBtnOnClickListener);
+			_toggleTouchModeBtnIcon.setOnClickListener(touchModeBtnOnClickListener);
 			_toggleKeyboardBtnIcon.setOnClickListener(keyboardBtnOnClickListener);
 			_openMenuBtnIcon.setOnClickListener(menuBtnOnClickListener);
 			_revokeSafPermissionsBtnIcon.setOnClickListener(revokeSafPermissionsBtnOnClickListener);
@@ -1391,8 +1411,8 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
 			_openMenuBtnIcon.setVisibility(show ? View.VISIBLE : View.GONE);
 		}
 
-		if (_toggleGamepadBtnIcon != null ) {
-			_toggleGamepadBtnIcon.setVisibility(show ? View.VISIBLE : View.GONE);
+		if (_toggleTouchModeBtnIcon != null ) {
+			_toggleTouchModeBtnIcon.setVisibility(show ? View.VISIBLE : View.GONE);
 		}
 	}
 
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMEventsBase.java b/backends/platform/android/org/scummvm/scummvm/ScummVMEventsBase.java
index d1dba19c3af..ffbe79496a1 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMEventsBase.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMEventsBase.java
@@ -55,6 +55,11 @@ public class ScummVMEventsBase implements
 	public static final int JACTION_UP = 2;
 	public static final int JACTION_CANCEL = 3;
 
+	public static final int TOUCH_MODE_TOUCHPAD = 0;
+	public static final int TOUCH_MODE_MOUSE = 1;
+	public static final int TOUCH_MODE_GAMEPAD = 2;
+	public static final int TOUCH_MODE_MAX = 3;
+
 	final protected Context _context;
 	final protected ScummVM _scummvm;
 	final protected GestureDetector _gd;
@@ -62,7 +67,7 @@ public class ScummVMEventsBase implements
 	final protected MouseHelper _mouseHelper;
 	final protected MultitouchHelper _multitouchHelper;
 
-	protected boolean _touch3DMode;
+	protected int _touchMode;
 
 	// Custom handler code (to avoid mem leaks, see warning "This Handler Class Should Be Static Or Leaks Might Occur”) based on:
 	// https://stackoverflow.com/a/27826094
@@ -142,15 +147,36 @@ public class ScummVMEventsBase implements
 		}
 	}
 
-	final public boolean getTouch3DMode() {
-		return _touch3DMode;
+	final public int getTouchMode() {
+		return _touchMode;
 	}
 
-	final public void setTouch3DMode(boolean touch3DMode) {
-		if (_touch3DMode != touch3DMode && !touch3DMode) {
+	final public void setTouchMode(int touchMode) {
+		assert (touchMode >= 0) && (touchMode < TOUCH_MODE_MAX);
+
+		if (_touchMode == touchMode) {
+			return;
+		}
+
+		if (_touchMode == TOUCH_MODE_GAMEPAD) {
+			// We were in gamepad mode and we leave it
 			_scummvm.updateTouch(JACTION_CANCEL, 0, 0, 0);
 		}
-		_touch3DMode = touch3DMode;
+		int oldTouchMode = _touchMode;
+		_touchMode = touchMode;
+		_scummvm.setupTouchMode(oldTouchMode, _touchMode);
+	}
+
+	final public int nextTouchMode() {
+		if (_touchMode == TOUCH_MODE_GAMEPAD) {
+			// We leave gamepad mode
+			_scummvm.updateTouch(JACTION_CANCEL, 0, 0, 0);
+		}
+		int oldTouchMode = _touchMode;
+		_touchMode = (_touchMode + 1) % TOUCH_MODE_MAX;
+		_scummvm.setupTouchMode(oldTouchMode, _touchMode);
+
+		return _touchMode;
 	}
 
 	public void clearEventHandler() {
@@ -477,7 +503,7 @@ public class ScummVMEventsBase implements
 			}
 		}
 
-		if (_touch3DMode) {
+		if (_touchMode == TOUCH_MODE_GAMEPAD) {
 			switch (event.getActionMasked()) {
 				case MotionEvent.ACTION_DOWN:
 				case MotionEvent.ACTION_POINTER_DOWN: {
@@ -528,7 +554,7 @@ public class ScummVMEventsBase implements
 	@Override
 	final public boolean onDown(MotionEvent e) {
 //		Log.d(ScummVM.LOG_TAG, "SCUMMV-EVENTS-BASE - onDOWN MotionEvent");
-		if (!_touch3DMode) {
+		if (_touchMode != TOUCH_MODE_GAMEPAD) {
 			_scummvm.pushEvent(JE_DOWN, (int)e.getX(), (int)e.getY(), 0, 0, 0, 0);
 		}
 		return true;
@@ -553,7 +579,7 @@ public class ScummVMEventsBase implements
 	final public boolean onScroll(MotionEvent e1, MotionEvent e2,
 									float distanceX, float distanceY) {
 //		Log.d(ScummVM.LOG_TAG, "onScroll");
-		if (!_touch3DMode) {
+		if (_touchMode != TOUCH_MODE_GAMEPAD) {
 			// typical use:
 			// - move mouse cursor around (most traditional point and click games)
 			// - mouse look (eg. Myst 3)
@@ -570,7 +596,7 @@ public class ScummVMEventsBase implements
 	@Override
 	final public boolean onSingleTapUp(MotionEvent e) {
 //		Log.d(ScummVM.LOG_TAG, "onSingleTapUp");
-		if (!_touch3DMode) {
+		if (_touchMode != TOUCH_MODE_GAMEPAD) {
 			_scummvm.pushEvent(JE_TAP, (int)e.getX(), (int)e.getY(),
 							(int)(e.getEventTime() - e.getDownTime()), 0, 0, 0);
 		}
@@ -598,7 +624,7 @@ public class ScummVMEventsBase implements
 //		} else {
 //			Log.d(ScummVM.LOG_TAG, "onDoubleTapEvent UNKNOWN!!!!");
 //		}
-		if (!_touch3DMode) {
+		if (_touchMode != TOUCH_MODE_GAMEPAD) {
 			_scummvm.pushEvent(JE_DOUBLE_TAP, (int)e.getX(), (int)e.getY(), e.getAction(), 0, 0, 0);
 		}
 		return true;
diff --git a/dists/android/res/drawable/ic_action_touchpad.xml b/dists/android/res/drawable/ic_action_touchpad.xml
new file mode 100644
index 00000000000..3959ccb6f8e
--- /dev/null
+++ b/dists/android/res/drawable/ic_action_touchpad.xml
@@ -0,0 +1,17 @@
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:name="vector"
+    android:width="48dp"
+    android:height="48dp"
+    android:viewportWidth="48"
+    android:viewportHeight="48"
+    android:alpha="0.5">
+  <path
+      android:fillColor="#ffffff"
+      android:pathData="M37.78,29.5l-8.18,-4.08c-0.56,-0.28 -1.16,-0.42 -1.78,-0.42H26.0v-12.0C26.0,11.34 24.66,10.0 23.0,10.0S20.0,11.34 20.0,13.0v21.48L13.5,33.0c-0.66,-0.14 -1.36,0.06 -1.84,0.56L10.0,35.24l9.08,9.58C19.84,45.58 21.36,46.0 22.42,46.0h12.32c2.0,0.0 3.68,-1.46 3.96,-3.44l1.26,-8.92C40.2,31.94 39.32,30.28 37.78,29.5z"
+	  android:strokeWidth="1"/>
+  <path
+      android:fillColor="#ffffff"
+      android:pathData="M40.26,7.74C37.38,4.34 31.2,2.0 24.0,2.0S10.62,4.34 7.74,7.74L4.0,4.0v10.0h10.0L9.86,9.86c2.0,-2.58 7.4,-4.86 14.14,-4.86s12.14,2.28 14.14,4.86L34.0,14.0h10.0V4.0L40.26,7.74z"
+	  android:strokeWidth="1"/>
+</vector>


Commit: 27de1f114506b98a67e66a424b5d479225f66493
    https://github.com/scummvm/scummvm/commit/27de1f114506b98a67e66a424b5d479225f66493
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-06-17T21:35:34+02:00

Commit Message:
ANDROID: Merge touch mode and toggle keyboard buttons

A long press on the button shows the keyboard

Changed paths:
    backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java


diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index 9e21ba67058..88cfae76437 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -118,8 +118,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
 	FrameLayout _videoLayout = null;
 
 	private EditableSurfaceView _main_surface = null;
-	private ImageView _toggleTouchModeBtnIcon = null;
-	private ImageView _toggleKeyboardBtnIcon = null;
+	private ImageView _toggleTouchModeKeyboardBtnIcon = null;
 	private ImageView _openMenuBtnIcon = null;
 	private ImageView _revokeSafPermissionsBtnIcon = null;
 
@@ -142,7 +141,6 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
 		super.onConfigurationChanged(newConfig);
 
 		final boolean hwKeyboard = isHWKeyboardConnected();
-		_toggleKeyboardBtnIcon.setVisibility(hwKeyboard ? View.GONE : View.VISIBLE);
 		if (hwKeyboard) {
 			hideScreenKeyboard();
 		}
@@ -520,6 +518,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
 				//Log.d(ScummVM.LOG_TAG, "showScreenKeyboard - captureMouse(false)");
 				_main_surface.captureMouse(false);
 				//_main_surface.showSystemMouseCursor(true);
+				setupTouchModeBtn(_events.getTouchMode());
 				return;
 			}
 			//Log.d(ScummVM.LOG_TAG, "showScreenKeyboard: YOU SHOULD NOT SEE ME!!!");
@@ -541,6 +540,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
 				//Log.d(ScummVM.LOG_TAG, "hideScreenKeyboard - captureMouse(true)");
 				_main_surface.captureMouse(true);
 				//_main_surface.showSystemMouseCursor(false);
+				setupTouchModeBtn(_events.getTouchMode());
 			}
 		}
 	}
@@ -573,43 +573,55 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
 	protected void setupTouchModeBtn(final int touchMode) {
 		int resId;
 
-		switch(touchMode) {
-		case ScummVMEventsBase.TOUCH_MODE_TOUCHPAD:
-			resId = R.drawable.ic_action_touchpad;
-			break;
-		case ScummVMEventsBase.TOUCH_MODE_MOUSE:
-			resId = R.drawable.ic_action_mouse;
-			break;
-		case ScummVMEventsBase.TOUCH_MODE_GAMEPAD:
-			resId = R.drawable.ic_action_gamepad;
-			break;
-		default:
-			throw new IllegalArgumentException("Invalid touchMode");
-		}
-
-		_toggleTouchModeBtnIcon.setImageResource(resId);
+		if (isScreenKeyboardShown()) {
+			resId = R.drawable.ic_action_keyboard;
+		} else {
+			switch(touchMode) {
+			case ScummVMEventsBase.TOUCH_MODE_TOUCHPAD:
+				resId = R.drawable.ic_action_touchpad;
+				break;
+			case ScummVMEventsBase.TOUCH_MODE_MOUSE:
+				resId = R.drawable.ic_action_mouse;
+				break;
+			case ScummVMEventsBase.TOUCH_MODE_GAMEPAD:
+				resId = R.drawable.ic_action_gamepad;
+				break;
+			default:
+				throw new IllegalArgumentException("Invalid touchMode");
+			}
+		}
+
+		_toggleTouchModeKeyboardBtnIcon.setImageResource(resId);
 	}
 
-	public final View.OnClickListener touchModeBtnOnClickListener = new View.OnClickListener() {
+	public final View.OnClickListener touchModeKeyboardBtnOnClickListener = new View.OnClickListener() {
 		@Override
 		public void onClick(View v) {
 			runOnUiThread(new Runnable() {
 				public void run() {
-					int newTouchMode = _events.nextTouchMode();
-					setupTouchModeBtn(newTouchMode);
+					// On normal click, hide keyboard if it is shown
+					// Else, change touch mode
+					if (isScreenKeyboardShown()) {
+						hideScreenKeyboard();
+					} else {
+						int newTouchMode = _events.nextTouchMode();
+						setupTouchModeBtn(newTouchMode);
+					}
 				}
 			});
 		}
 	};
 
-	public final View.OnClickListener keyboardBtnOnClickListener = new View.OnClickListener() {
+	public final View.OnLongClickListener touchModeKeyboardBtnOnLongClickListener = new View.OnLongClickListener() {
 		@Override
-		public void onClick(View v) {
+		public boolean onLongClick(View v) {
 			runOnUiThread(new Runnable() {
 				public void run() {
+					// On long click, toggle screen keyboard (if there isn't any HW)
 					toggleScreenKeyboard();
 				}
 			});
+			return true;
 		}
 	};
 
@@ -1028,14 +1040,9 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
 		_videoLayout.addView(buttonLayout, buttonLayoutParams);
 		_videoLayout.bringChildToFront(buttonLayout);
 
-		_toggleTouchModeBtnIcon = new ImageView(this);
-		buttonLayout.addView(_toggleTouchModeBtnIcon, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT));
-		buttonLayout.bringChildToFront(_toggleTouchModeBtnIcon);
-
-		_toggleKeyboardBtnIcon = new ImageView(this);
-		_toggleKeyboardBtnIcon.setImageResource(R.drawable.ic_action_keyboard);
-		buttonLayout.addView(_toggleKeyboardBtnIcon, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT));
-		buttonLayout.bringChildToFront(_toggleKeyboardBtnIcon);
+		_toggleTouchModeKeyboardBtnIcon = new ImageView(this);
+		buttonLayout.addView(_toggleTouchModeKeyboardBtnIcon, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT));
+		buttonLayout.bringChildToFront(_toggleTouchModeKeyboardBtnIcon);
 
 		_openMenuBtnIcon = new ImageView(this);
 		_openMenuBtnIcon.setImageResource(R.drawable.ic_action_menu);
@@ -1143,8 +1150,8 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
 
 			// On screen button listener
 			//findViewById(R.id.show_keyboard).setOnClickListener(keyboardBtnOnClickListener);
-			_toggleTouchModeBtnIcon.setOnClickListener(touchModeBtnOnClickListener);
-			_toggleKeyboardBtnIcon.setOnClickListener(keyboardBtnOnClickListener);
+			_toggleTouchModeKeyboardBtnIcon.setOnClickListener(touchModeKeyboardBtnOnClickListener);
+			_toggleTouchModeKeyboardBtnIcon.setOnLongClickListener(touchModeKeyboardBtnOnLongClickListener);
 			_openMenuBtnIcon.setOnClickListener(menuBtnOnClickListener);
 			_revokeSafPermissionsBtnIcon.setOnClickListener(revokeSafPermissionsBtnOnClickListener);
 
@@ -1398,21 +1405,12 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
 	// Show or hide the semi-transparent onscreen controls
 	// Called by the override of showKeyboardControl()
 	private void showToggleKeyboardBtnIcon(boolean show) {
-		//ImageView keyboardBtn = findViewById(R.id.show_keyboard);
-		if (_toggleKeyboardBtnIcon != null ) {
-			if (show && !isHWKeyboardConnected()) {
-				_toggleKeyboardBtnIcon.setVisibility(View.VISIBLE);
-			} else {
-				_toggleKeyboardBtnIcon.setVisibility(View.GONE);
-			}
-		}
-
 		if (_openMenuBtnIcon != null ) {
 			_openMenuBtnIcon.setVisibility(show ? View.VISIBLE : View.GONE);
 		}
 
-		if (_toggleTouchModeBtnIcon != null ) {
-			_toggleTouchModeBtnIcon.setVisibility(show ? View.VISIBLE : View.GONE);
+		if (_toggleTouchModeKeyboardBtnIcon != null ) {
+			_toggleTouchModeKeyboardBtnIcon.setVisibility(show ? View.VISIBLE : View.GONE);
 		}
 	}
 


Commit: a125b0e3f15cf3b61691de329198e4780bc1644d
    https://github.com/scummvm/scummvm/commit/a125b0e3f15cf3b61691de329198e4780bc1644d
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2022-06-17T21:35:34+02:00

Commit Message:
DOCS: Update Android docs to match new touch controls settings

Changed paths:
    doc/docportal/other_platforms/android.rst


diff --git a/doc/docportal/other_platforms/android.rst b/doc/docportal/other_platforms/android.rst
index a1df492676d..da352a0e09d 100644
--- a/doc/docportal/other_platforms/android.rst
+++ b/doc/docportal/other_platforms/android.rst
@@ -86,7 +86,6 @@ Controls can also be manually configured in the :doc:`Keymaps tab <../settings/k
         Short press system Back button, "Skip, or Cancel/Quit in the Launcher"
         Long press system Menu button, Opens/closes Virtual keyboard
         Short press system Menu button, Opens Global Main Menu
-        Small keyboard icon (top right), Opens/closes Virtual keyboard
         D-pad up/down/left/right, Mouse movement
         D-pad center, Left mouse button click
         Trackball movement, Mouse movement
@@ -94,12 +93,18 @@ Controls can also be manually configured in the :doc:`Keymaps tab <../settings/k
 
 Touch controls
 ****************
-The touch control scheme can be switched in the global settings. From the Launcher, go to **Options > Backend > Touchpad mouse mode**.
+The touch control scheme can be configured in the global settings. From the Launcher, go to **Options > Backend > Choose the preferred touch mode**.
+It's possible to configure the touch mode for three situations (ScummVM menus, 2D games and 3D games) and choose one of the three possible modes:
 
-    - When touchpad mouse mode is off (default), the touch controls are direct. The pointer jumps to where the finger touches the screen.
-    - When touchpad mouse mode is on, the touch controls are indirect. The finger can be far away from the pointer and still move it, like on a laptop touchpad.
+    - Direct mouse, the touch controls are direct. The pointer jumps to where the finger touches the screen (default for menus).
+    - Touchpad emulation, the touch controls are indirect. The finger can be far away from the pointer and still move it, like on a laptop touchpad.
+    - Gamepad emulation, the touch controls don't move any mouse. The fingers must be placed on lower left and right of the screen and respectively emulate a directional pad and action buttons.
     - The pointer speed setting in the :doc:`Controls tab <../settings/control>` affects how far the pointer moves in response to a finger movement.
 
+The touch mode can be switched at anytime by tapping on the controller icon, next to the menu icon at the top right of the screen.
+
+To display or hide the small controller icon, from the Launcher select **Options** and then the **Backend** tab. Tick the **Show on-screen control** box to enable the controller icon.
+
 Two finger tap
 ^^^^^^^^^^^^^^^^^
 
@@ -125,10 +130,7 @@ To display or hide the small menu icon, from the Launcher select **Options** and
 Virtual keyboard
 ^^^^^^^^^^^^^^^^^^^^^
 
-To open the virtual keyboard, tap on the small keyboard icon at the top right of the screen, or tap on any editable text field. To hide the virtual keyboard, tap the small keyboard icon again, or tap outside the text field.
-
-To display or hide the small keyboard icon, from the Launcher select **Options** and then the **Backend** tab. Tick the **Show on-screen control** box to enable the keyboard icon.
-
+To open the virtual keyboard, long press on the small controller icon at the top right of the screen, or tap on any editable text field. To hide the virtual keyboard, tap the small controller icon (which became a keyboard one) again, or tap outside the text field.
 
 Paths
 =======




More information about the Scummvm-git-logs mailing list