浏览代码

Merge pull request #105015 from syntaxerror247/improve-touchActionsPanel

Android Editor: Add an editor setting to enable/disable `TouchActionsPanel`
Thaddeus Crews 5 月之前
父节点
当前提交
1b9f269700

+ 8 - 0
doc/classes/DisplayServer.xml

@@ -1204,6 +1204,14 @@
 				[b]Note:[/b] On iOS, this method has no effect if [member ProjectSettings.display/window/handheld/orientation] is not set to [constant SCREEN_SENSOR].
 				[b]Note:[/b] On iOS, this method has no effect if [member ProjectSettings.display/window/handheld/orientation] is not set to [constant SCREEN_SENSOR].
 			</description>
 			</description>
 		</method>
 		</method>
+		<method name="set_hardware_keyboard_connection_change_callback">
+			<return type="void" />
+			<param index="0" name="callable" type="Callable" />
+			<description>
+				Sets the [param callable] that should be called when hardware keyboard is connected/disconnected. [param callable] should accept a single [bool] parameter indicating whether the keyboard is connected (true) or disconnected (false).
+				[b]Note:[/b] This method is only implemented on Android.
+			</description>
+		</method>
 		<method name="set_icon">
 		<method name="set_icon">
 			<return type="void" />
 			<return type="void" />
 			<param index="0" name="image" type="Image" />
 			<param index="0" name="image" type="Image" />

+ 4 - 0
doc/classes/EditorSettings.xml

@@ -1102,6 +1102,10 @@
 			If [code]true[/code], enable two finger pan and scale gestures on touchscreen devices.
 			If [code]true[/code], enable two finger pan and scale gestures on touchscreen devices.
 			[b]Note:[/b] Defaults to [code]true[/code] on touchscreen devices.
 			[b]Note:[/b] Defaults to [code]true[/code] on touchscreen devices.
 		</member>
 		</member>
+		<member name="interface/touchscreen/enable_touch_actions_panel" type="bool" setter="" getter="">
+			If [code]true[/code], enables the TouchActionsPanel to provide easy access to keyboard shortcuts on touchscreen devices.
+			[b]Note:[/b] Only available in the Android editor.
+		</member>
 		<member name="interface/touchscreen/increase_scrollbar_touch_area" type="bool" setter="" getter="">
 		<member name="interface/touchscreen/increase_scrollbar_touch_area" type="bool" setter="" getter="">
 			If [code]true[/code], increases the scrollbar touch area to improve usability on touchscreen devices.
 			If [code]true[/code], increases the scrollbar touch area to improve usability on touchscreen devices.
 			[b]Note:[/b] Defaults to [code]true[/code] on touchscreen devices.
 			[b]Note:[/b] Defaults to [code]true[/code] on touchscreen devices.

+ 4 - 1
editor/editor_node.cpp

@@ -7955,7 +7955,10 @@ EditorNode::EditorNode() {
 
 
 #ifdef ANDROID_ENABLED
 #ifdef ANDROID_ENABLED
 	// Add TouchActionsPanel node.
 	// Add TouchActionsPanel node.
-	add_child(memnew(TouchActionsPanel));
+	bool is_enabled = EDITOR_GET("interface/touchscreen/enable_touch_actions_panel");
+	if (is_enabled) {
+		add_child(memnew(TouchActionsPanel));
+	}
 #endif
 #endif
 
 
 	// Bottom panels.
 	// Bottom panels.

+ 4 - 0
editor/editor_settings.cpp

@@ -584,6 +584,10 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
 	EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/touchscreen/scale_gizmo_handles", has_touchscreen_ui ? 3 : 1, "1,5,1")
 	EDITOR_SETTING(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/touchscreen/scale_gizmo_handles", has_touchscreen_ui ? 3 : 1, "1,5,1")
 	set_restart_if_changed("interface/touchscreen/scale_gizmo_handles", true);
 	set_restart_if_changed("interface/touchscreen/scale_gizmo_handles", true);
 
 
+	// Only available in the Android editor.
+	EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/touchscreen/enable_touch_actions_panel", true, "")
+	set_restart_if_changed("interface/touchscreen/enable_touch_actions_panel", true);
+
 	// Disable some touchscreen settings by default for the XR Editor.
 	// Disable some touchscreen settings by default for the XR Editor.
 	bool is_native_touchscreen = has_touchscreen_ui && !OS::get_singleton()->has_feature("xr_editor");
 	bool is_native_touchscreen = has_touchscreen_ui && !OS::get_singleton()->has_feature("xr_editor");
 	EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/touchscreen/enable_long_press_as_right_click", is_native_touchscreen, "")
 	EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/touchscreen/enable_long_press_as_right_click", is_native_touchscreen, "")

+ 8 - 0
editor/gui/touch_actions_panel.cpp

@@ -41,6 +41,10 @@
 
 
 void TouchActionsPanel::_notification(int p_what) {
 void TouchActionsPanel::_notification(int p_what) {
 	switch (p_what) {
 	switch (p_what) {
+		case NOTIFICATION_ENTER_TREE: {
+			DisplayServer::get_singleton()->set_hardware_keyboard_connection_change_callback(callable_mp(this, &TouchActionsPanel::_hardware_keyboard_connected));
+			_hardware_keyboard_connected(DisplayServer::get_singleton()->has_hardware_keyboard());
+		} break;
 		case NOTIFICATION_THEME_CHANGED: {
 		case NOTIFICATION_THEME_CHANGED: {
 			drag_handle->set_texture(get_editor_theme_icon(SNAME("DragHandle")));
 			drag_handle->set_texture(get_editor_theme_icon(SNAME("DragHandle")));
 			layout_toggle_button->set_button_icon(get_editor_theme_icon(SNAME("Orientation")));
 			layout_toggle_button->set_button_icon(get_editor_theme_icon(SNAME("Orientation")));
@@ -53,6 +57,10 @@ void TouchActionsPanel::_notification(int p_what) {
 	}
 	}
 }
 }
 
 
+void TouchActionsPanel::_hardware_keyboard_connected(bool p_connected) {
+	set_visible(!p_connected);
+}
+
 void TouchActionsPanel::_simulate_editor_shortcut(const String &p_shortcut_name) {
 void TouchActionsPanel::_simulate_editor_shortcut(const String &p_shortcut_name) {
 	Ref<Shortcut> shortcut = ED_GET_SHORTCUT(p_shortcut_name);
 	Ref<Shortcut> shortcut = ED_GET_SHORTCUT(p_shortcut_name);
 
 

+ 2 - 0
editor/gui/touch_actions_panel.h

@@ -63,6 +63,8 @@ private:
 	void _lock_panel_toggled(bool p_pressed);
 	void _lock_panel_toggled(bool p_pressed);
 	Button *_add_new_action_button(const String &p_shortcut, Key p_keycode = Key::NONE);
 	Button *_add_new_action_button(const String &p_shortcut, Key p_keycode = Key::NONE);
 
 
+	void _hardware_keyboard_connected(bool p_connected);
+
 public:
 public:
 	TouchActionsPanel();
 	TouchActionsPanel();
 };
 };

+ 10 - 0
platform/android/display_server_android.cpp

@@ -145,6 +145,16 @@ void DisplayServerAndroid::emit_system_theme_changed() {
 	}
 	}
 }
 }
 
 
+void DisplayServerAndroid::set_hardware_keyboard_connection_change_callback(const Callable &p_callable) {
+	hardware_keyboard_connection_changed = p_callable;
+}
+
+void DisplayServerAndroid::emit_hardware_keyboard_connection_changed(bool p_connected) {
+	if (hardware_keyboard_connection_changed.is_valid()) {
+		hardware_keyboard_connection_changed.call_deferred(p_connected);
+	}
+}
+
 void DisplayServerAndroid::clipboard_set(const String &p_text) {
 void DisplayServerAndroid::clipboard_set(const String &p_text) {
 	GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();
 	GodotJavaWrapper *godot_java = OS_Android::get_singleton()->get_godot_java();
 	ERR_FAIL_NULL(godot_java);
 	ERR_FAIL_NULL(godot_java);

+ 4 - 2
platform/android/display_server_android.h

@@ -89,6 +89,7 @@ class DisplayServerAndroid : public DisplayServer {
 	Callable rect_changed_callback;
 	Callable rect_changed_callback;
 
 
 	Callable system_theme_changed;
 	Callable system_theme_changed;
+	Callable hardware_keyboard_connection_changed;
 
 
 	Callable dialog_callback;
 	Callable dialog_callback;
 	Callable input_dialog_callback;
 	Callable input_dialog_callback;
@@ -114,11 +115,10 @@ public:
 	virtual void tts_resume() override;
 	virtual void tts_resume() override;
 	virtual void tts_stop() override;
 	virtual void tts_stop() override;
 
 
-	void emit_system_theme_changed();
-
 	virtual bool is_dark_mode_supported() const override;
 	virtual bool is_dark_mode_supported() const override;
 	virtual bool is_dark_mode() const override;
 	virtual bool is_dark_mode() const override;
 	virtual void set_system_theme_change_callback(const Callable &p_callable) override;
 	virtual void set_system_theme_change_callback(const Callable &p_callable) override;
+	void emit_system_theme_changed();
 
 
 	virtual void clipboard_set(const String &p_text) override;
 	virtual void clipboard_set(const String &p_text) override;
 	virtual String clipboard_get() const override;
 	virtual String clipboard_get() const override;
@@ -159,6 +159,8 @@ public:
 	virtual void virtual_keyboard_hide() override;
 	virtual void virtual_keyboard_hide() override;
 	virtual int virtual_keyboard_get_height() const override;
 	virtual int virtual_keyboard_get_height() const override;
 	virtual bool has_hardware_keyboard() const override;
 	virtual bool has_hardware_keyboard() const override;
+	virtual void set_hardware_keyboard_connection_change_callback(const Callable &p_callable) override;
+	void emit_hardware_keyboard_connection_changed(bool p_connected);
 
 
 	virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
 	virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
 	virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
 	virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;

+ 0 - 1
platform/android/java/lib/src/org/godotengine/godot/Godot.kt

@@ -77,7 +77,6 @@ import org.godotengine.godot.xr.XRMode
 import java.io.File
 import java.io.File
 import java.io.FileInputStream
 import java.io.FileInputStream
 import java.io.InputStream
 import java.io.InputStream
-import java.lang.Exception
 import java.security.MessageDigest
 import java.security.MessageDigest
 import java.util.*
 import java.util.*
 import java.util.concurrent.atomic.AtomicBoolean
 import java.util.concurrent.atomic.AtomicBoolean

+ 5 - 0
platform/android/java/lib/src/org/godotengine/godot/GodotLib.java

@@ -268,6 +268,11 @@ public class GodotLib {
 	 */
 	 */
 	public static native void onNightModeChanged();
 	public static native void onNightModeChanged();
 
 
+	/**
+	 * Invoked on the hardware keyboard connected/disconnected.
+	 */
+	public static native void hardwareKeyboardConnected(boolean connected);
+
 	/**
 	/**
 	 * Invoked on the file picker closed.
 	 * Invoked on the file picker closed.
 	 */
 	 */

+ 0 - 7
platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java

@@ -265,13 +265,6 @@ public class GodotEditText extends EditText {
 	}
 	}
 
 
 	public boolean hasHardwareKeyboard() {
 	public boolean hasHardwareKeyboard() {
-		Configuration config = getResources().getConfiguration();
-		boolean hasHardwareKeyboardConfig = config.keyboard != Configuration.KEYBOARD_NOKEYS &&
-				config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO;
-		if (hasHardwareKeyboardConfig) {
-			return true;
-		}
-
 		return mRenderView.getInputHandler().hasHardwareKeyboard();
 		return mRenderView.getInputHandler().hasHardwareKeyboard();
 	}
 	}
 
 

+ 14 - 0
platform/android/java/lib/src/org/godotengine/godot/input/GodotInputHandler.java

@@ -90,6 +90,7 @@ public class GodotInputHandler implements InputManager.InputDeviceListener, Sens
 
 
 	private int cachedRotation = -1;
 	private int cachedRotation = -1;
 	private boolean overrideVolumeButtons = false;
 	private boolean overrideVolumeButtons = false;
+	private boolean hasHardwareKeyboardConfig = false;
 
 
 	public GodotInputHandler(Context context, Godot godot) {
 	public GodotInputHandler(Context context, Godot godot) {
 		this.godot = godot;
 		this.godot = godot;
@@ -105,6 +106,9 @@ public class GodotInputHandler implements InputManager.InputDeviceListener, Sens
 		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
 		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
 			this.scaleGestureDetector.setStylusScaleEnabled(true);
 			this.scaleGestureDetector.setStylusScaleEnabled(true);
 		}
 		}
+		Configuration config = context.getResources().getConfiguration();
+		hasHardwareKeyboardConfig = config.keyboard != Configuration.KEYBOARD_NOKEYS &&
+				config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO;
 	}
 	}
 
 
 	/**
 	/**
@@ -143,6 +147,9 @@ public class GodotInputHandler implements InputManager.InputDeviceListener, Sens
 	}
 	}
 
 
 	boolean hasHardwareKeyboard() {
 	boolean hasHardwareKeyboard() {
+		if (hasHardwareKeyboardConfig) {
+			return true;
+		}
 		return !mHardwareKeyboardIds.isEmpty();
 		return !mHardwareKeyboardIds.isEmpty();
 	}
 	}
 
 
@@ -797,5 +804,12 @@ public class GodotInputHandler implements InputManager.InputDeviceListener, Sens
 
 
 	public void onConfigurationChanged(Configuration newConfig) {
 	public void onConfigurationChanged(Configuration newConfig) {
 		updateCachedRotation();
 		updateCachedRotation();
+
+		boolean newHardwareKeyboardConfig = newConfig.keyboard != Configuration.KEYBOARD_NOKEYS &&
+				newConfig.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO;
+		if (hasHardwareKeyboardConfig != newHardwareKeyboardConfig) {
+			hasHardwareKeyboardConfig = newHardwareKeyboardConfig;
+			GodotLib.hardwareKeyboardConnected(hasHardwareKeyboard());
+		}
 	}
 	}
 }
 }

+ 7 - 0
platform/android/java_godot_lib_jni.cpp

@@ -548,6 +548,13 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onNightModeChanged(JN
 	}
 	}
 }
 }
 
 
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hardwareKeyboardConnected(JNIEnv *env, jclass clazz, jboolean p_connected) {
+	DisplayServerAndroid *ds = (DisplayServerAndroid *)DisplayServer::get_singleton();
+	if (ds) {
+		ds->emit_hardware_keyboard_connection_changed(p_connected);
+	}
+}
+
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_filePickerCallback(JNIEnv *env, jclass clazz, jboolean p_ok, jobjectArray p_selected_paths) {
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_filePickerCallback(JNIEnv *env, jclass clazz, jboolean p_ok, jobjectArray p_selected_paths) {
 	DisplayServerAndroid *ds = (DisplayServerAndroid *)DisplayServer::get_singleton();
 	DisplayServerAndroid *ds = (DisplayServerAndroid *)DisplayServer::get_singleton();
 	if (ds) {
 	if (ds) {

+ 1 - 0
platform/android/java_godot_lib_jni.h

@@ -68,6 +68,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setEditorProjectMetad
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHeight(JNIEnv *env, jclass clazz, jint p_height);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHeight(JNIEnv *env, jclass clazz, jint p_height);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResult(JNIEnv *env, jclass clazz, jstring p_permission, jboolean p_result);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_requestPermissionResult(JNIEnv *env, jclass clazz, jstring p_permission, jboolean p_result);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onNightModeChanged(JNIEnv *env, jclass clazz);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onNightModeChanged(JNIEnv *env, jclass clazz);
+JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_hardwareKeyboardConnected(JNIEnv *env, jclass clazz, jboolean p_connected);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_filePickerCallback(JNIEnv *env, jclass clazz, jboolean p_ok, jobjectArray p_selected_paths);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_filePickerCallback(JNIEnv *env, jclass clazz, jboolean p_ok, jobjectArray p_selected_paths);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererResumed(JNIEnv *env, jclass clazz);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererResumed(JNIEnv *env, jclass clazz);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererPaused(JNIEnv *env, jclass clazz);
 JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_onRendererPaused(JNIEnv *env, jclass clazz);

+ 1 - 0
servers/display_server.cpp

@@ -1033,6 +1033,7 @@ void DisplayServer::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("virtual_keyboard_get_height"), &DisplayServer::virtual_keyboard_get_height);
 	ClassDB::bind_method(D_METHOD("virtual_keyboard_get_height"), &DisplayServer::virtual_keyboard_get_height);
 
 
 	ClassDB::bind_method(D_METHOD("has_hardware_keyboard"), &DisplayServer::has_hardware_keyboard);
 	ClassDB::bind_method(D_METHOD("has_hardware_keyboard"), &DisplayServer::has_hardware_keyboard);
+	ClassDB::bind_method(D_METHOD("set_hardware_keyboard_connection_change_callback", "callable"), &DisplayServer::set_hardware_keyboard_connection_change_callback);
 
 
 	ClassDB::bind_method(D_METHOD("cursor_set_shape", "shape"), &DisplayServer::cursor_set_shape);
 	ClassDB::bind_method(D_METHOD("cursor_set_shape", "shape"), &DisplayServer::cursor_set_shape);
 	ClassDB::bind_method(D_METHOD("cursor_get_shape"), &DisplayServer::cursor_get_shape);
 	ClassDB::bind_method(D_METHOD("cursor_get_shape"), &DisplayServer::cursor_get_shape);

+ 1 - 0
servers/display_server.h

@@ -272,6 +272,7 @@ public:
 	virtual Color get_accent_color() const { return Color(0, 0, 0, 0); }
 	virtual Color get_accent_color() const { return Color(0, 0, 0, 0); }
 	virtual Color get_base_color() const { return Color(0, 0, 0, 0); }
 	virtual Color get_base_color() const { return Color(0, 0, 0, 0); }
 	virtual void set_system_theme_change_callback(const Callable &p_callable) {}
 	virtual void set_system_theme_change_callback(const Callable &p_callable) {}
+	virtual void set_hardware_keyboard_connection_change_callback(const Callable &p_callable) {}
 
 
 private:
 private:
 	static bool window_early_clear_override_enabled;
 	static bool window_early_clear_override_enabled;