Browse Source

Allow toggling touchscreen mode at runtime (#14075)

Signed-off-by: David Heidelberg <david@ixit.cz>
Co-authored-by: Gregor Parzefall <gregor.parzefall@posteo.de>
David Heidelberg 2 months ago
parent
commit
34286d77c7

+ 0 - 7
.luacheckrc

@@ -71,7 +71,6 @@ files["builtin/mainmenu"] = {
 
 	read_globals = {
 		"PLATFORM",
-		"TOUCHSCREEN_GUI",
 	},
 }
 
@@ -82,9 +81,3 @@ files["builtin/common/tests"] = {
 		"assert",
 	},
 }
-
-files["builtin/fstk"] = {
-	read_globals = {
-		"TOUCHSCREEN_GUI",
-	},
-}

+ 8 - 6
builtin/fstk/buttonbar.lua

@@ -18,7 +18,9 @@
 
 
 local BASE_SPACING = 0.1
-local SCROLL_BTN_WIDTH = TOUCHSCREEN_GUI and 0.8 or 0.5
+local function get_scroll_btn_width()
+	return core.settings:get_bool("enable_touch") and 0.8 or 0.5
+end
 
 local function buttonbar_formspec(self)
 	if self.hidden then
@@ -39,7 +41,7 @@ local function buttonbar_formspec(self)
 
 	-- The number of buttons per page is always calculated as if the scroll
     -- buttons were visible.
-	local avail_space = self.size.x - 2*BASE_SPACING - 2*SCROLL_BTN_WIDTH
+	local avail_space = self.size.x - 2*BASE_SPACING - 2*get_scroll_btn_width()
 	local btns_per_page = math.floor((avail_space - BASE_SPACING) / (btn_size + BASE_SPACING))
 
 	self.num_pages = math.ceil(#self.buttons / btns_per_page)
@@ -55,7 +57,7 @@ local function buttonbar_formspec(self)
 
 	local btn_start_x = self.pos.x + btn_spacing
 	if show_scroll_btns then
-		btn_start_x = btn_start_x + BASE_SPACING + SCROLL_BTN_WIDTH
+		btn_start_x = btn_start_x + BASE_SPACING + get_scroll_btn_width()
 	end
 
 	for i = first_btn, first_btn + btns_per_page - 1 do
@@ -80,7 +82,7 @@ local function buttonbar_formspec(self)
 			y = self.pos.y + BASE_SPACING,
 		}
 		local btn_next_pos = {
-			x = self.pos.x + self.size.x - BASE_SPACING - SCROLL_BTN_WIDTH,
+			x = self.pos.x + self.size.x - BASE_SPACING - get_scroll_btn_width(),
 			y = self.pos.y + BASE_SPACING,
 		}
 
@@ -88,11 +90,11 @@ local function buttonbar_formspec(self)
 				self.btn_prev_name, self.btn_next_name))
 
 		table.insert(formspec, string.format("button[%f,%f;%f,%f;%s;<]",
-				btn_prev_pos.x, btn_prev_pos.y, SCROLL_BTN_WIDTH, btn_size,
+				btn_prev_pos.x, btn_prev_pos.y, get_scroll_btn_width(), btn_size,
 				self.btn_prev_name))
 
 		table.insert(formspec, string.format("button[%f,%f;%f,%f;%s;>]",
-				btn_next_pos.x, btn_next_pos.y, SCROLL_BTN_WIDTH, btn_size,
+				btn_next_pos.x, btn_next_pos.y, get_scroll_btn_width(), btn_size,
 				self.btn_next_name))
 	end
 

+ 4 - 4
builtin/mainmenu/content/dlg_contentstore.lua

@@ -898,7 +898,7 @@ local function get_info_formspec(text)
 	return table.concat({
 		"formspec_version[6]",
 		"size[15.75,9.5]",
-		TOUCHSCREEN_GUI and "padding[0.01,0.01]" or "position[0.5,0.55]",
+		core.settings:get_bool("enable_touch") and "padding[0.01,0.01]" or "position[0.5,0.55]",
 
 		"label[4,4.35;", text, "]",
 		"container[0,", H - 0.8 - 0.375, "]",
@@ -928,7 +928,7 @@ function store.get_formspec(dlgdata)
 	local formspec = {
 		"formspec_version[6]",
 		"size[15.75,9.5]",
-		TOUCHSCREEN_GUI and "padding[0.01,0.01]" or "position[0.5,0.55]",
+		core.settings:get_bool("enable_touch") and "padding[0.01,0.01]" or "position[0.5,0.55]",
 
 		"style[status,downloading,queued;border=false]",
 
@@ -1175,8 +1175,8 @@ end
 
 function store.handle_events(event)
 	if event == "DialogShow" then
-		-- On mobile, don't show the "MINETEST" header behind the dialog.
-		mm_game_theme.set_engine(TOUCHSCREEN_GUI)
+		-- On touchscreen, don't show the "MINETEST" header behind the dialog.
+		mm_game_theme.set_engine(core.settings:get_bool("enable_touch"))
 
 		-- If the store is already loaded, auto-install packages here.
 		do_auto_install()

+ 19 - 8
builtin/mainmenu/settings/dlg_settings.lua

@@ -316,8 +316,8 @@ local function check_requirements(name, requires)
 	local special = {
 		android = PLATFORM == "Android",
 		desktop = PLATFORM ~= "Android",
-		touchscreen_gui = TOUCHSCREEN_GUI,
-		keyboard_mouse = not TOUCHSCREEN_GUI,
+		touchscreen_gui = core.settings:get_bool("enable_touch"),
+		keyboard_mouse = not core.settings:get_bool("enable_touch"),
 		shaders_support = shaders_support,
 		shaders = core.settings:get_bool("enable_shaders") and shaders_support,
 		opengl = video_driver == "opengl",
@@ -449,13 +449,13 @@ local function get_formspec(dialogdata)
 
 	local extra_h = 1 -- not included in tabsize.height
 	local tabsize = {
-		width = TOUCHSCREEN_GUI and 16.5 or 15.5,
-		height = TOUCHSCREEN_GUI and (10 - extra_h) or 12,
+		width = core.settings:get_bool("enable_touch") and 16.5 or 15.5,
+		height = core.settings:get_bool("enable_touch") and (10 - extra_h) or 12,
 	}
 
-	local scrollbar_w = TOUCHSCREEN_GUI and 0.6 or 0.4
+	local scrollbar_w = core.settings:get_bool("enable_touch") and 0.6 or 0.4
 
-	local left_pane_width = TOUCHSCREEN_GUI and 4.5 or 4.25
+	local left_pane_width = core.settings:get_bool("enable_touch") and 4.5 or 4.25
 	local search_width = left_pane_width + scrollbar_w - (0.75 * 2)
 
 	local back_w = 3
@@ -468,7 +468,7 @@ local function get_formspec(dialogdata)
 	local fs = {
 		"formspec_version[6]",
 		"size[", tostring(tabsize.width), ",", tostring(tabsize.height + extra_h), "]",
-		TOUCHSCREEN_GUI and "padding[0.01,0.01]" or "",
+		core.settings:get_bool("enable_touch") and "padding[0.01,0.01]" or "",
 		"bgcolor[#0000]",
 
 		-- HACK: this is needed to allow resubmitting the same formspec
@@ -641,11 +641,22 @@ local function buttonhandler(this, fields)
 		local value = core.is_yes(fields.show_advanced)
 		core.settings:set_bool("show_advanced", value)
 		write_settings_early()
+	end
+
+	-- enable_touch is a checkbox in a setting component. We handle this
+	-- setting differently so we can hide/show pages using the next if-statement
+	if fields.enable_touch ~= nil then
+		local value = core.is_yes(fields.enable_touch)
+		core.settings:set_bool("enable_touch", value)
+		write_settings_early()
+	end
 
+	if fields.show_advanced ~= nil or fields.enable_touch ~= nil then
 		local suggested_page_id = update_filtered_pages(dialogdata.query)
 
+		dialogdata.components = nil
+
 		if not filtered_page_by_id[dialogdata.page_id] then
-			dialogdata.components = nil
 			dialogdata.leftscroll = 0
 			dialogdata.rightscroll = 0
 

+ 1 - 1
builtin/mainmenu/tab_local.lua

@@ -94,7 +94,7 @@ function singleplayer_refresh_gamebar()
 
 	local btnbar = buttonbar_create(
 			"game_button_bar",
-			TOUCHSCREEN_GUI and {x = 0, y = 7.25} or {x = 0, y = 7.475},
+			core.settings:get_bool("enable_touch") and {x = 0, y = 7.25} or {x = 0, y = 7.475},
 			{x = 15.5, y = 1.25},
 			"#000000",
 			game_buttonbar_button_handler)

+ 5 - 0
builtin/settingtypes.txt

@@ -148,6 +148,11 @@ invert_hotbar_mouse_wheel (Hotbar: Invert mouse wheel direction) bool false
 
 [*Touchscreen]
 
+#    Enables touchscreen mode, allowing you to play the game with a touchscreen.
+#
+#    Requires: !android
+enable_touch (Enable touchscreen) bool true
+
 #    The length in pixels it takes for touchscreen interaction to start.
 #
 #    Requires: touchscreen_gui

+ 1 - 1
doc/compiling/README.md

@@ -38,7 +38,7 @@ General options and their default values:
     INSTALL_DEVTEST=FALSE      - Whether the Development Test game should be installed alongside Minetest
     USE_GPROF=FALSE            - Enable profiling using GProf
     VERSION_EXTRA=             - Text to append to version (e.g. VERSION_EXTRA=foobar -> Minetest 0.4.9-foobar)
-    ENABLE_TOUCH=FALSE         - Enable Touchscreen support (requires support by IrrlichtMt)
+    ENABLE_TOUCH=FALSE         - Enable touchscreen support by default (requires support by IrrlichtMt)
 
 Library specific options:
 

+ 3 - 2
src/CMakeLists.txt

@@ -109,9 +109,10 @@ if(BUILD_CLIENT AND ENABLE_SOUND)
 	endif()
 endif()
 
-option(ENABLE_TOUCH "Enable Touchscreen support" FALSE)
+option(ENABLE_TOUCH "Enable touchscreen by default" FALSE)
 if(ENABLE_TOUCH)
-	add_definitions(-DHAVE_TOUCHSCREENGUI)
+	message(STATUS "Touchscreen support enabled by default.")
+	add_definitions(-DENABLE_TOUCH)
 endif()
 
 if(BUILD_CLIENT)

+ 9 - 9
src/client/clientlauncher.cpp

@@ -249,10 +249,10 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args)
 			m_rendering_engine->get_video_driver()->setTextureCreationFlag(
 					video::ETCF_CREATE_MIP_MAPS, g_settings->getBool("mip_map"));
 
-#ifdef HAVE_TOUCHSCREENGUI
-			receiver->m_touchscreengui = new TouchScreenGUI(m_rendering_engine->get_raw_device(), receiver);
-			g_touchscreengui = receiver->m_touchscreengui;
-#endif
+			if (g_settings->getBool("enable_touch")) {
+				receiver->m_touchscreengui = new TouchScreenGUI(m_rendering_engine->get_raw_device(), receiver);
+				g_touchscreengui = receiver->m_touchscreengui;
+			}
 
 			the_game(
 				kill,
@@ -283,11 +283,11 @@ bool ClientLauncher::run(GameStartData &start_data, const Settings &cmd_args)
 
 		m_rendering_engine->get_scene_manager()->clear();
 
-#ifdef HAVE_TOUCHSCREENGUI
-		delete g_touchscreengui;
-		g_touchscreengui = NULL;
-		receiver->m_touchscreengui = NULL;
-#endif
+		if (g_touchscreengui) {
+			delete g_touchscreengui;
+			g_touchscreengui = NULL;
+			receiver->m_touchscreengui = NULL;
+		}
 
 		/* Save the settings when leaving the game.
 		 * This makes sure that setting changes made in-game are persisted even

+ 39 - 75
src/client/game.cpp

@@ -664,11 +664,7 @@ public:
 	}
 };
 
-#ifdef HAVE_TOUCHSCREENGUI
-#define SIZE_TAG "size[11,5.5]"
-#else
-#define SIZE_TAG "size[11,5.5,true]" // Fixed size on desktop
-#endif
+#define SIZE_TAG "size[11,5.5,true]" // Fixed size (ignored in touchscreen mode)
 
 /****************************************************************************
  ****************************************************************************/
@@ -1021,13 +1017,11 @@ private:
 	// this happens in pause menu in singleplayer
 	bool m_is_paused = false;
 
-#ifdef HAVE_TOUCHSCREENGUI
-	bool m_cache_hold_aux1;
+	bool m_touch_simulate_aux1 = false;
 	bool m_touch_use_crosshair;
-	inline bool isNoCrosshairAllowed() {
+	inline bool isTouchCrosshairDisabled() {
 		return !m_touch_use_crosshair && camera->getCameraMode() == CAMERA_MODE_FIRST;
 	}
-#endif
 #ifdef __ANDROID__
 	bool m_android_chat_open;
 #endif
@@ -1075,11 +1069,6 @@ Game::Game() :
 		&settingChangedCallback, this);
 
 	readSettings();
-
-#ifdef HAVE_TOUCHSCREENGUI
-	m_cache_hold_aux1 = false;	// This is initialised properly later
-#endif
-
 }
 
 
@@ -1182,9 +1171,7 @@ bool Game::startup(bool *kill,
 
 	m_first_loop_after_window_activation = true;
 
-#ifdef HAVE_TOUCHSCREENGUI
 	m_touch_use_crosshair = g_settings->getBool("touch_use_crosshair");
-#endif
 
 	g_client_translations->clear();
 
@@ -1219,10 +1206,8 @@ void Game::run()
 
 	set_light_table(g_settings->getFloat("display_gamma"));
 
-#ifdef HAVE_TOUCHSCREENGUI
-	m_cache_hold_aux1 = g_settings->getBool("fast_move")
+	m_touch_simulate_aux1 = g_settings->getBool("fast_move")
 			&& client->checkPrivilege("fast");
-#endif
 
 	const irr::core::dimension2du initial_screen_size(
 			g_settings->getU16("screen_w"),
@@ -1308,9 +1293,8 @@ void Game::shutdown()
 	// Clear text when exiting.
 	m_game_ui->clearText();
 
-#ifdef HAVE_TOUCHSCREENGUI
-	g_touchscreengui->hide();
-#endif
+	if (g_touchscreengui)
+		g_touchscreengui->hide();
 
 	showOverlayMessage(N_("Shutting down..."), 0, 0, false);
 
@@ -1520,11 +1504,10 @@ bool Game::createClient(const GameStartData &start_data)
 	if (client->modsLoaded())
 		client->getScript()->on_camera_ready(camera);
 	client->setCamera(camera);
-#ifdef HAVE_TOUCHSCREENGUI
+
 	if (g_touchscreengui) {
-		g_touchscreengui->setUseCrosshair(!isNoCrosshairAllowed());
+		g_touchscreengui->setUseCrosshair(!isTouchCrosshairDisabled());
 	}
-#endif
 
 	/* Clouds
 	 */
@@ -1594,10 +1577,8 @@ bool Game::initGui()
 	gui_chat_console = new GUIChatConsole(guienv, guienv->getRootGUIElement(),
 			-1, chat_backend, client, &g_menumgr);
 
-#ifdef HAVE_TOUCHSCREENGUI
 	if (g_touchscreengui)
 		g_touchscreengui->init(texture_src);
-#endif
 
 	return true;
 }
@@ -2026,18 +2007,17 @@ void Game::processUserInput(f32 dtime)
 		} else {
 			input->clear();
 		}
-#ifdef HAVE_TOUCHSCREENGUI
-		g_touchscreengui->hide();
-#endif
+
+		if (g_touchscreengui)
+			g_touchscreengui->hide();
+
 	} else {
-#ifdef HAVE_TOUCHSCREENGUI
 		if (g_touchscreengui) {
 			/* on touchscreengui step may generate own input events which ain't
 			 * what we want in case we just did clear them */
 			g_touchscreengui->show();
 			g_touchscreengui->step(dtime);
 		}
-#endif
 
 		m_game_focused = true;
 	}
@@ -2229,13 +2209,11 @@ void Game::processItemSelection(u16 *new_playeritem)
 		}
 	}
 
-#ifdef HAVE_TOUCHSCREENGUI
 	if (g_touchscreengui) {
 		std::optional<u16> selection = g_touchscreengui->getHotbarSelection();
 		if (selection)
 			*new_playeritem = *selection;
 	}
-#endif
 
 	// Clamp selection again in case it wasn't changed but max_item was
 	*new_playeritem = MYMIN(*new_playeritem, max_item);
@@ -2386,9 +2364,7 @@ void Game::toggleFast()
 		m_game_ui->showTranslatedStatusText("Fast mode disabled");
 	}
 
-#ifdef HAVE_TOUCHSCREENGUI
-	m_cache_hold_aux1 = fast_move && has_fast_privs;
-#endif
+	m_touch_simulate_aux1 = fast_move && has_fast_privs;
 }
 
 
@@ -2633,10 +2609,8 @@ void Game::updateCameraDirection(CameraOrientation *cam, float dtime)
 	Since Minetest has its own code to synthesize mouse events from touch events,
 	this results in duplicated input. To avoid that, we don't enable relative
 	mouse mode if we're in touchscreen mode. */
-#ifndef HAVE_TOUCHSCREENGUI
 	if (cur_control)
-		cur_control->setRelativeMode(!isMenuActive());
-#endif
+		cur_control->setRelativeMode(!g_touchscreengui && !isMenuActive());
 
 	if ((device->isWindowActive() && device->isWindowFocused()
 			&& !isMenuActive()) || input->isRandom()) {
@@ -2679,12 +2653,10 @@ f32 Game::getSensitivityScaleFactor() const
 
 void Game::updateCameraOrientation(CameraOrientation *cam, float dtime)
 {
-#ifdef HAVE_TOUCHSCREENGUI
 	if (g_touchscreengui) {
 		cam->camera_yaw   += g_touchscreengui->getYawChange();
 		cam->camera_pitch += g_touchscreengui->getPitchChange();
 	} else {
-#endif
 		v2s32 center(driver->getScreenSize().Width / 2, driver->getScreenSize().Height / 2);
 		v2s32 dist = input->getMousePos() - center;
 
@@ -2698,9 +2670,7 @@ void Game::updateCameraOrientation(CameraOrientation *cam, float dtime)
 
 		if (dist.X != 0 || dist.Y != 0)
 			input->setMousePos(center.X, center.Y);
-#ifdef HAVE_TOUCHSCREENGUI
 	}
-#endif
 
 	if (m_cache_enable_joysticks) {
 		f32 sens_scale = getSensitivityScaleFactor();
@@ -2745,16 +2715,14 @@ void Game::updatePlayerControl(const CameraOrientation &cam)
 		control.movement_direction = atan2(dx, 1.0f);
 	}
 
-#ifdef HAVE_TOUCHSCREENGUI
 	/* For touch, simulate holding down AUX1 (fast move) if the user has
 	 * the fast_move setting toggled on. If there is an aux1 key defined for
 	 * touch then its meaning is inverted (i.e. holding aux1 means walk and
 	 * not fast)
 	 */
-	if (m_cache_hold_aux1) {
+	if (g_touchscreengui && m_touch_simulate_aux1) {
 		control.aux1 = control.aux1 ^ true;
 	}
-#endif
 
 	client->setPlayerControl(control);
 
@@ -3235,10 +3203,8 @@ void Game::updateCamera(f32 dtime)
 
 		camera->toggleCameraMode();
 
-#ifdef HAVE_TOUCHSCREENGUI
 		if (g_touchscreengui)
-			g_touchscreengui->setUseCrosshair(!isNoCrosshairAllowed());
-#endif
+			g_touchscreengui->setUseCrosshair(!isTouchCrosshairDisabled());
 
 		// Make the player visible depending on camera mode.
 		playercao->updateMeshCulling();
@@ -3339,8 +3305,7 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud)
 	}
 	shootline.end = shootline.start + camera_direction * BS * d;
 
-#ifdef HAVE_TOUCHSCREENGUI
-	if (g_touchscreengui && isNoCrosshairAllowed()) {
+	if (g_touchscreengui && isTouchCrosshairDisabled()) {
 		shootline = g_touchscreengui->getShootline();
 		// Scale shootline to the acual distance the player can reach
 		shootline.end = shootline.start +
@@ -3348,7 +3313,6 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud)
 		shootline.start += intToFloat(camera_offset, BS);
 		shootline.end += intToFloat(camera_offset, BS);
 	}
-#endif
 
 	PointedThing pointed = updatePointedThing(shootline,
 			selected_def.liquids_pointable,
@@ -3359,10 +3323,8 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud)
 	if (pointed != runData.pointed_old)
 		infostream << "Pointing at " << pointed.dump() << std::endl;
 
-#ifdef HAVE_TOUCHSCREENGUI
 	if (g_touchscreengui)
 		g_touchscreengui->applyContextControls(selected_def.touch_interaction.getMode(pointed));
-#endif
 
 	// Note that updating the selection mesh every frame is not particularly efficient,
 	// but the halo rendering code is already inefficient so there's no point in optimizing it here
@@ -4345,10 +4307,10 @@ void Game::drawScene(ProfilerGraph *graph, RunStats *stats)
 	bool draw_crosshair = (
 			(player->hud_flags & HUD_FLAG_CROSSHAIR_VISIBLE) &&
 			(this->camera->getCameraMode() != CAMERA_MODE_THIRD_FRONT));
-#ifdef HAVE_TOUCHSCREENGUI
-	if (this->isNoCrosshairAllowed())
+
+	if (g_touchscreengui && isTouchCrosshairDisabled())
 		draw_crosshair = false;
-#endif
+
 	this->m_rendering_engine->draw_scene(sky_color, this->m_game_ui->m_flags.show_hud,
 			draw_wield_tool, draw_crosshair);
 
@@ -4496,21 +4458,23 @@ void Game::showDeathFormspec()
 #define GET_KEY_NAME(KEY) gettext(getKeySetting(#KEY).name())
 void Game::showPauseMenu()
 {
-#ifdef HAVE_TOUCHSCREENGUI
-	static const std::string control_text = strgettext("Controls:\n"
-		"No menu open:\n"
-		"- slide finger: look around\n"
-		"- tap: place/punch/use (default)\n"
-		"- long tap: dig/use (default)\n"
-		"Menu/inventory open:\n"
-		"- double tap (outside):\n"
-		" --> close\n"
-		"- touch stack, touch slot:\n"
-		" --> move stack\n"
-		"- touch&drag, tap 2nd finger\n"
-		" --> place single item to slot\n"
-		);
-#endif
+	std::string control_text;
+
+	if (g_touchscreengui) {
+		control_text = strgettext("Controls:\n"
+			"No menu open:\n"
+			"- slide finger: look around\n"
+			"- tap: place/punch/use (default)\n"
+			"- long tap: dig/use (default)\n"
+			"Menu/inventory open:\n"
+			"- double tap (outside):\n"
+			" --> close\n"
+			"- touch stack, touch slot:\n"
+			" --> move stack\n"
+			"- touch&drag, tap 2nd finger\n"
+			" --> place single item to slot\n"
+			);
+	}
 
 	float ypos = simple_singleplayer_mode ? 0.7f : 0.1f;
 	std::ostringstream os;
@@ -4540,9 +4504,9 @@ void Game::showPauseMenu()
 		<< strgettext("Exit to Menu") << "]";
 	os		<< "button_exit[4," << (ypos++) << ";3,0.5;btn_exit_os;"
 		<< strgettext("Exit to OS")   << "]";
-#ifdef HAVE_TOUCHSCREENGUI
+	if (!control_text.empty()) {
 	os		<< "textarea[7.5,0.25;3.9,6.25;;" << control_text << ";]";
-#endif
+	}
 	os		<< "textarea[0.4,0.25;3.9,6.25;;" << PROJECT_NAME_C " " VERSION_STRING "\n"
 		<< "\n"
 		<<  strgettext("Game info:") << "\n";

+ 0 - 7
src/client/hud.cpp

@@ -39,10 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "wieldmesh.h"
 #include "client/renderingengine.h"
 #include "client/minimap.h"
-
-#ifdef HAVE_TOUCHSCREENGUI
 #include "gui/touchscreengui.h"
-#endif
 
 #define OBJECT_CROSSHAIR_LINE_SIZE 8
 #define CROSSHAIR_LINE_SIZE 10
@@ -292,10 +289,8 @@ void Hud::drawItems(v2s32 upperleftpos, v2s32 screen_offset, s32 itemcount,
 
 		drawItem(mainlist->getItem(i), item_rect, (i + 1) == selectitem);
 
-#ifdef HAVE_TOUCHSCREENGUI
 		if (is_hotbar && g_touchscreengui)
 			g_touchscreengui->registerHotbarRect(i, item_rect);
-#endif
 	}
 }
 
@@ -749,10 +744,8 @@ void Hud::drawStatbar(v2s32 pos, u16 corner, u16 drawdir,
 
 void Hud::drawHotbar(u16 playeritem)
 {
-#ifdef HAVE_TOUCHSCREENGUI
 	if (g_touchscreengui)
 		g_touchscreengui->resetHotbarRects();
-#endif
 
 	InventoryList *mainlist = inventory->getList("main");
 	if (mainlist == NULL) {

+ 0 - 4
src/client/inputhandler.cpp

@@ -102,11 +102,9 @@ bool MyEventReceiver::OnEvent(const SEvent &event)
 		React to nothing here if a menu is active
 	*/
 	if (isMenuActive()) {
-#ifdef HAVE_TOUCHSCREENGUI
 		if (m_touchscreengui) {
 			m_touchscreengui->setVisible(false);
 		}
-#endif
 		return g_menumgr.preprocessEvent(event);
 	}
 
@@ -130,12 +128,10 @@ bool MyEventReceiver::OnEvent(const SEvent &event)
 			return true;
 		}
 
-#ifdef HAVE_TOUCHSCREENGUI
 	} else if (m_touchscreengui && event.EventType == irr::EET_TOUCH_INPUT_EVENT) {
 		// In case of touchscreengui, we have to handle different events
 		m_touchscreengui->translateEvent(event);
 		return true;
-#endif
 
 	} else if (event.EventType == irr::EET_JOYSTICK_INPUT_EVENT) {
 		// joystick may be nullptr if game is launched with '--random-input' parameter

+ 4 - 16
src/client/inputhandler.h

@@ -24,10 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <list>
 #include "keycode.h"
 #include "renderingengine.h"
-
-#ifdef HAVE_TOUCHSCREENGUI
 #include "gui/touchscreengui.h"
-#endif
 
 class InputHandler;
 
@@ -203,16 +200,12 @@ public:
 
 	MyEventReceiver()
 	{
-#ifdef HAVE_TOUCHSCREENGUI
 		m_touchscreengui = NULL;
-#endif
 	}
 
 	JoystickController *joystick = nullptr;
 
-#ifdef HAVE_TOUCHSCREENGUI
 	TouchScreenGUI *m_touchscreengui;
-#endif
 
 private:
 	s32 mouse_wheel = 0;
@@ -332,11 +325,9 @@ public:
 				return 0.0f;
 			return 1.0f; // If there is a keyboard event, assume maximum speed
 		}
-#ifdef HAVE_TOUCHSCREENGUI
-		return m_receiver->m_touchscreengui->getMovementSpeed();
-#else
+		if (m_receiver->m_touchscreengui && m_receiver->m_touchscreengui->getMovementSpeed())
+			return m_receiver->m_touchscreengui->getMovementSpeed();
 		return joystick.getMovementSpeed();
-#endif
 	}
 
 	virtual float getMovementDirection()
@@ -355,12 +346,9 @@ public:
 
 		if (x != 0 || z != 0) /* If there is a keyboard event, it takes priority */
 			return atan2(x, z);
-		else
-#ifdef HAVE_TOUCHSCREENGUI
+		else if (m_receiver->m_touchscreengui && m_receiver->m_touchscreengui->getMovementDirection())
 			return m_receiver->m_touchscreengui->getMovementDirection();
-#else
-			return joystick.getMovementDirection();
-#endif
+		return joystick.getMovementDirection();
 	}
 
 	virtual bool cancelPressed()

+ 0 - 8
src/client/keycode.cpp

@@ -18,7 +18,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 */
 
 #include "keycode.h"
-#include "exceptions.h"
 #include "settings.h"
 #include "log.h"
 #include "debug.h"
@@ -26,13 +25,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "util/string.h"
 #include "util/basic_macros.h"
 
-class UnknownKeycode : public BaseException
-{
-public:
-	UnknownKeycode(const char *s) :
-		BaseException(s) {};
-};
-
 struct table_key {
 	const char *Name;
 	irr::EKEY_CODE Key;

+ 8 - 0
src/client/keycode.h

@@ -19,11 +19,19 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #pragma once
 
+#include "exceptions.h"
 #include "irrlichttypes.h"
 #include "Keycodes.h"
 #include <IEventReceiver.h>
 #include <string>
 
+class UnknownKeycode : public BaseException
+{
+public:
+	UnknownKeycode(const char *s) :
+		BaseException(s) {};
+};
+
 /* A key press, consisting of either an Irrlicht keycode
    or an actual char */
 

+ 3 - 11
src/clientdynamicinfo.h

@@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef SERVER
 #include "settings.h"
 #include "client/renderingengine.h"
+#include "gui/touchscreengui.h"
 #endif
 
 
@@ -50,11 +51,7 @@ public:
 		f32 hud_scaling = g_settings->getFloat("hud_scaling", 0.5f, 20.0f);
 		f32 real_gui_scaling = gui_scaling * density;
 		f32 real_hud_scaling = hud_scaling * density;
-#ifdef HAVE_TOUCHSCREENGUI
-		bool touch_controls = true;
-#else
-		bool touch_controls = false;
-#endif
+		bool touch_controls = g_touchscreengui;
 
 		return {
 			screen_size, real_gui_scaling, real_hud_scaling,
@@ -67,12 +64,7 @@ public:
 private:
 #ifndef SERVER
 	static v2f32 calculateMaxFSSize(v2u32 render_target_size, f32 gui_scaling) {
-		f32 factor =
-#ifdef HAVE_TOUCHSCREENGUI
-				10 / gui_scaling;
-#else
-				15 / gui_scaling;
-#endif
+		f32 factor = (g_settings->getBool("enable_touch") ? 10 : 15) / gui_scaling;
 		f32 ratio = (f32)render_target_size.X / (f32)render_target_size.Y;
 		if (ratio < 1)
 			return { factor, factor / ratio };

+ 12 - 4
src/defaultsettings.cpp

@@ -39,6 +39,11 @@ void set_default_settings()
 	// Client
 	settings->setDefault("address", "");
 	settings->setDefault("enable_sound", "true");
+#if ENABLE_TOUCH
+	settings->setDefault("enable_touch", "true");
+#else
+	settings->setDefault("enable_touch", "false");
+#endif
 	settings->setDefault("sound_volume", "0.8");
 	settings->setDefault("sound_volume_unfocused", "0.3");
 	settings->setDefault("mute_sound", "false");
@@ -90,7 +95,7 @@ void set_default_settings()
 	settings->setDefault("keymap_cmd_local", ".");
 	settings->setDefault("keymap_minimap", "KEY_KEY_V");
 	settings->setDefault("keymap_console", "KEY_F10");
-#if HAVE_TOUCHSCREENGUI
+#if ENABLE_TOUCH
 	// See https://github.com/minetest/minetest/issues/12792
 	settings->setDefault("keymap_rangeselect", "KEY_KEY_R");
 #else
@@ -192,7 +197,11 @@ void set_default_settings()
 	settings->setDefault("screen_h", "600");
 	settings->setDefault("window_maximized", "false");
 	settings->setDefault("autosave_screensize", "true");
+#ifdef ENABLE_TOUCH
+	settings->setDefault("fullscreen", "true");
+#else
 	settings->setDefault("fullscreen", "false");
+#endif
 	settings->setDefault("vsync", "false");
 	settings->setDefault("fov", "72");
 	settings->setDefault("leaves_style", "fancy");
@@ -298,7 +307,7 @@ void set_default_settings()
 	settings->setDefault("aux1_descends", "false");
 	settings->setDefault("doubletap_jump", "false");
 	settings->setDefault("always_fly_fast", "true");
-#ifdef HAVE_TOUCHSCREENGUI
+#ifdef ENABLE_TOUCH
 	settings->setDefault("autojump", "true");
 #else
 	settings->setDefault("autojump", "false");
@@ -477,12 +486,12 @@ void set_default_settings()
 	settings->setDefault("keymap_sneak", "KEY_SHIFT");
 #endif
 
-#ifdef HAVE_TOUCHSCREENGUI
 	settings->setDefault("touchscreen_threshold", "20");
 	settings->setDefault("touchscreen_sensitivity", "0.2");
 	settings->setDefault("touch_use_crosshair", "false");
 	settings->setDefault("fixed_virtual_joystick", "false");
 	settings->setDefault("virtual_joystick_triggers_aux1", "false");
+#ifdef ENABLE_TOUCH
 	settings->setDefault("clickable_chat_weblinks", "false");
 #else
 	settings->setDefault("clickable_chat_weblinks", "true");
@@ -491,7 +500,6 @@ void set_default_settings()
 #ifdef __ANDROID__
 	settings->setDefault("screen_w", "0");
 	settings->setDefault("screen_h", "0");
-	settings->setDefault("fullscreen", "true");
 	settings->setDefault("performance_tradeoffs", "true");
 	settings->setDefault("max_simultaneous_block_sends_per_client", "10");
 	settings->setDefault("emergequeue_limit_diskonly", "16");

+ 1 - 6
src/gui/CMakeLists.txt

@@ -1,8 +1,3 @@
-set(extra_gui_SRCS "")
-if(ENABLE_TOUCH)
-	set(extra_gui_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/touchscreengui.cpp)
-endif()
-
 set(gui_SRCS
 	${CMAKE_CURRENT_SOURCE_DIR}/guiAnimatedImage.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/guiBackgroundImage.cpp
@@ -29,6 +24,6 @@ set(gui_SRCS
 	${CMAKE_CURRENT_SOURCE_DIR}/guiVolumeChange.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/modalMenu.cpp
 	${CMAKE_CURRENT_SOURCE_DIR}/profilergraph.cpp
-	${extra_gui_SRCS}
+	${CMAKE_CURRENT_SOURCE_DIR}/touchscreengui.cpp
 	PARENT_SCOPE
 )

+ 10 - 11
src/gui/guiFormSpecMenu.cpp

@@ -316,13 +316,11 @@ void GUIFormSpecMenu::parseSize(parserData* data, const std::string &element)
 		data->invsize.Y = MYMAX(0, stof(parts[1]));
 
 		lockSize(false);
-#ifndef HAVE_TOUCHSCREENGUI
-		if (parts.size() == 3) {
+		if (!g_settings->getBool("enable_touch") && parts.size() == 3) {
 			if (parts[2] == "true") {
 				lockSize(true,v2u32(800,600));
 			}
 		}
-#endif
 		data->explicit_size = true;
 		return;
 	}
@@ -3284,14 +3282,15 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
 
 			s32 min_screen_dim = std::min(padded_screensize.X, padded_screensize.Y);
 
-#ifdef HAVE_TOUCHSCREENGUI
-			// In Android, the preferred imgsize should be larger to accommodate the
-			// smaller screensize.
-			double prefer_imgsize = min_screen_dim / 10 * gui_scaling;
-#else
-			// Desktop computers have more space, so try to fit 15 coordinates.
-			double prefer_imgsize = min_screen_dim / 15 * gui_scaling;
-#endif
+			double prefer_imgsize;
+			if (g_settings->getBool("enable_touch")) {
+				// The preferred imgsize should be larger to accommodate the
+				// smaller screensize.
+				prefer_imgsize = min_screen_dim / 10 * gui_scaling;
+			} else {
+				// Desktop computers have more space, so try to fit 15 coordinates.
+				prefer_imgsize = min_screen_dim / 15 * gui_scaling;
+			}
 			// Try to use the preferred imgsize, but if that's bigger than the maximum
 			// size, use the maximum size.
 			use_imgsize = std::min(prefer_imgsize,

+ 1 - 8
src/gui/guiPasswordChange.cpp

@@ -25,10 +25,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #include <IGUIStaticText.h>
 #include <IGUIFont.h>
 
-#ifdef HAVE_TOUCHSCREENGUI
-	#include "client/renderingengine.h"
-#endif
-
 #include "porting.h"
 #include "gettext.h"
 
@@ -66,11 +62,8 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
 	/*
 		Calculate new sizes and positions
 	*/
-#ifdef HAVE_TOUCHSCREENGUI
-	const float s = m_gui_scale * RenderingEngine::getDisplayDensity() / 2;
-#else
 	const float s = m_gui_scale;
-#endif
+
 	DesiredRect = core::rect<s32>(
 		screensize.X / 2 - 580 * s / 2,
 		screensize.Y / 2 - 300 * s / 2,

+ 6 - 10
src/gui/modalMenu.cpp

@@ -27,10 +27,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "gettext.h"
 #include "porting.h"
 #include "settings.h"
-
-#ifdef HAVE_TOUCHSCREENGUI
 #include "touchscreengui.h"
-#endif
 
 GUIModalMenu::GUIModalMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent,
 	s32 id, IMenuManager *menumgr, bool remap_dbl_click) :
@@ -44,11 +41,12 @@ GUIModalMenu::GUIModalMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent,
 {
 	m_gui_scale = std::max(g_settings->getFloat("gui_scaling"), 0.5f);
 	const float screen_dpi_scale = RenderingEngine::getDisplayDensity();
-#ifdef HAVE_TOUCHSCREENGUI
-	m_gui_scale *= 1.1f - 0.3f * screen_dpi_scale + 0.2f * screen_dpi_scale * screen_dpi_scale;
-#else
-	m_gui_scale *= screen_dpi_scale;
-#endif
+
+	if (g_settings->getBool("enable_touch")) {
+		m_gui_scale *= 1.1f - 0.3f * screen_dpi_scale + 0.2f * screen_dpi_scale * screen_dpi_scale;
+	} else {
+		m_gui_scale *= screen_dpi_scale;
+	}
 
 	setVisible(true);
 	m_menumgr->createdMenu(this);
@@ -102,10 +100,8 @@ void GUIModalMenu::quitMenu()
 	Environment->removeFocus(this);
 	m_menumgr->deletingMenu(this);
 	this->remove();
-#ifdef HAVE_TOUCHSCREENGUI
 	if (g_touchscreengui)
 		g_touchscreengui->show();
-#endif
 }
 
 static bool isChild(gui::IGUIElement *tocheck, gui::IGUIElement *parent)

+ 41 - 12
src/gui/touchscreengui.cpp

@@ -55,6 +55,7 @@ const std::string joystick_image_names[] = {
 
 static EKEY_CODE id_to_keycode(touch_gui_button_id id)
 {
+	EKEY_CODE code;
 	// ESC isn't part of the keymap.
 	if (id == exit_id)
 		return KEY_ESCAPE;
@@ -110,7 +111,15 @@ static EKEY_CODE id_to_keycode(touch_gui_button_id id)
 			break;
 	}
 	assert(!key.empty());
-	return keyname_to_keycode(g_settings->get("keymap_" + key).c_str());
+	std::string resolved = g_settings->get("keymap_" + key);
+	try {
+		code = keyname_to_keycode(resolved.c_str());
+	} catch (UnknownKeycode &e) {
+		code = KEY_UNKNOWN;
+		warningstream << "TouchScreenGUI: Unknown key '" << resolved
+			      << "' for '" << key << "', hiding button." << std::endl;
+	}
+	return code;
 }
 
 static void load_button_texture(const button_info *btn, const std::string &path,
@@ -523,13 +532,23 @@ void TouchScreenGUI::init(ISimpleTextureSource *tsrc)
 							+ 0.5f * button_size),
 			AHBB_Dir_Right_Left, 3.0f);
 
-	m_settings_bar.addButton(fly_id, L"fly", "fly_btn.png");
-	m_settings_bar.addButton(noclip_id, L"noclip", "noclip_btn.png");
-	m_settings_bar.addButton(fast_id, L"fast", "fast_btn.png");
-	m_settings_bar.addButton(debug_id, L"debug", "debug_btn.png");
-	m_settings_bar.addButton(camera_id, L"camera", "camera_btn.png");
-	m_settings_bar.addButton(range_id, L"rangeview", "rangeview_btn.png");
-	m_settings_bar.addButton(minimap_id, L"minimap", "minimap_btn.png");
+	const static std::map<touch_gui_button_id, std::string> settings_bar_buttons {
+		{fly_id, "fly"},
+		{noclip_id, "noclip"},
+		{fast_id, "fast"},
+		{debug_id, "debug"},
+		{camera_id, "camera"},
+		{range_id, "rangeview"},
+		{minimap_id, "minimap"},
+	};
+	for (const auto &pair : settings_bar_buttons) {
+		if (id_to_keycode(pair.first) == KEY_UNKNOWN)
+			continue;
+
+		std::wstring wide = utf8_to_wide(pair.second);
+		m_settings_bar.addButton(pair.first, wide.c_str(),
+				pair.second + "_btn.png");
+	}
 
 	// Chat is shown by default, so chat_hide_btn.png is shown first.
 	m_settings_bar.addToggleButton(toggle_chat_id, L"togglechat",
@@ -545,10 +564,20 @@ void TouchScreenGUI::init(ISimpleTextureSource *tsrc)
 							+ 0.5f * button_size),
 			AHBB_Dir_Left_Right, 2.0f);
 
-	m_rare_controls_bar.addButton(chat_id, L"chat", "chat_btn.png");
-	m_rare_controls_bar.addButton(inventory_id, L"inv", "inventory_btn.png");
-	m_rare_controls_bar.addButton(drop_id, L"drop", "drop_btn.png");
-	m_rare_controls_bar.addButton(exit_id, L"exit", "exit_btn.png");
+	const static std::map<touch_gui_button_id, std::string> rare_controls_bar_buttons {
+		{chat_id, "chat"},
+		{inventory_id, "inventory"},
+		{drop_id, "drop"},
+		{exit_id, "exit"},
+	};
+	for (const auto &pair : rare_controls_bar_buttons) {
+		if (id_to_keycode(pair.first) == KEY_UNKNOWN)
+			continue;
+
+		std::wstring wide = utf8_to_wide(pair.second);
+		m_rare_controls_bar.addButton(pair.first, wide.c_str(),
+				pair.second + "_btn.png");
+	}
 
 	m_initialized = true;
 }

+ 0 - 3
src/main.cpp

@@ -50,9 +50,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "gui/guiEngine.h"
 #include "gui/mainmenumanager.h"
 #endif
-#ifdef HAVE_TOUCHSCREENGUI
-	#include "gui/touchscreengui.h"
-#endif
 
 // for version information only
 extern "C" {

+ 0 - 7
src/script/cpp_api/s_base.cpp

@@ -153,13 +153,6 @@ ScriptApiBase::ScriptApiBase(ScriptingType type):
 	lua_pushstring(m_luastack, porting::getPlatformName());
 	lua_setglobal(m_luastack, "PLATFORM");
 
-#ifdef HAVE_TOUCHSCREENGUI
-	lua_pushboolean(m_luastack, true);
-#else
-	lua_pushboolean(m_luastack, false);
-#endif
-	lua_setglobal(m_luastack, "TOUCHSCREEN_GUI");
-
 	// Make sure Lua uses the right locale
 	setlocale(LC_NUMERIC, "C");
 }