Browse Source

Fix Android LineEdit editing bugs

SkyJJ 5 năm trước cách đây
mục cha
commit
cc473b948f

+ 2 - 2
platform/android/display_server_android.cpp

@@ -155,12 +155,12 @@ bool DisplayServerAndroid::screen_is_touchscreen(int p_screen) const {
 	return true;
 	return true;
 }
 }
 
 
-void DisplayServerAndroid::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_length) {
+void DisplayServerAndroid::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_length, int p_cursor_start, int p_cursor_end) {
 	GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();
 	GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();
 	ERR_FAIL_COND(!godot_io_java);
 	ERR_FAIL_COND(!godot_io_java);
 
 
 	if (godot_io_java->has_vk()) {
 	if (godot_io_java->has_vk()) {
-		godot_io_java->show_vk(p_existing_text, p_max_length);
+		godot_io_java->show_vk(p_existing_text, p_max_length, p_cursor_start, p_cursor_end);
 	} else {
 	} else {
 		ERR_PRINT("Virtual keyboard not available");
 		ERR_PRINT("Virtual keyboard not available");
 	}
 	}

+ 1 - 1
platform/android/display_server_android.h

@@ -106,7 +106,7 @@ public:
 	virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
 	virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
 	virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
 	virtual bool screen_is_touchscreen(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
 
 
-	virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_length = -1);
+	virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
 	virtual void virtual_keyboard_hide();
 	virtual void virtual_keyboard_hide();
 	virtual int virtual_keyboard_get_height() const;
 	virtual int virtual_keyboard_get_height() const;
 
 

+ 2 - 2
platform/android/java/lib/src/org/godotengine/godot/GodotIO.java

@@ -460,9 +460,9 @@ public class GodotIO {
 		return (int)(metrics.density * 160f);
 		return (int)(metrics.density * 160f);
 	}
 	}
 
 
-	public void showKeyboard(String p_existing_text, int p_max_input_length) {
+	public void showKeyboard(String p_existing_text, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
 		if (edit != null)
 		if (edit != null)
-			edit.showKeyboard(p_existing_text, p_max_input_length);
+			edit.showKeyboard(p_existing_text, p_max_input_length, p_cursor_start, p_cursor_end);
 
 
 		//InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
 		//InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
 		//inputMgr.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
 		//inputMgr.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

+ 27 - 12
platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java

@@ -58,6 +58,7 @@ public class GodotEditText extends EditText {
 	private GodotTextInputWrapper mInputWrapper;
 	private GodotTextInputWrapper mInputWrapper;
 	private EditHandler sHandler = new EditHandler(this);
 	private EditHandler sHandler = new EditHandler(this);
 	private String mOriginText;
 	private String mOriginText;
+	private int mMaxInputLength;
 
 
 	private static class EditHandler extends Handler {
 	private static class EditHandler extends Handler {
 		private final WeakReference<GodotEditText> mEdit;
 		private final WeakReference<GodotEditText> mEdit;
@@ -104,11 +105,18 @@ public class GodotEditText extends EditText {
 				String text = edit.mOriginText;
 				String text = edit.mOriginText;
 				if (edit.requestFocus()) {
 				if (edit.requestFocus()) {
 					edit.removeTextChangedListener(edit.mInputWrapper);
 					edit.removeTextChangedListener(edit.mInputWrapper);
+					setMaxInputLength(edit);
 					edit.setText("");
 					edit.setText("");
 					edit.append(text);
 					edit.append(text);
+					if (msg.arg2 != -1) {
+						edit.setSelection(msg.arg1, msg.arg2);
+						edit.mInputWrapper.setSelection(true);
+					} else {
+						edit.mInputWrapper.setSelection(false);
+					}
+
 					edit.mInputWrapper.setOriginText(text);
 					edit.mInputWrapper.setOriginText(text);
 					edit.addTextChangedListener(edit.mInputWrapper);
 					edit.addTextChangedListener(edit.mInputWrapper);
-					setMaxInputLength(edit, msg.arg1);
 					final InputMethodManager imm = (InputMethodManager)mRenderView.getView().getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
 					final InputMethodManager imm = (InputMethodManager)mRenderView.getView().getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
 					imm.showSoftInput(edit, 0);
 					imm.showSoftInput(edit, 0);
 				}
 				}
@@ -125,14 +133,10 @@ public class GodotEditText extends EditText {
 		}
 		}
 	}
 	}
 
 
-	private void setMaxInputLength(EditText p_edit_text, int p_max_input_length) {
-		if (p_max_input_length > 0) {
-			InputFilter[] filters = new InputFilter[1];
-			filters[0] = new InputFilter.LengthFilter(p_max_input_length);
-			p_edit_text.setFilters(filters);
-		} else {
-			p_edit_text.setFilters(new InputFilter[] {});
-		}
+	private void setMaxInputLength(EditText p_edit_text) {
+		InputFilter[] filters = new InputFilter[1];
+		filters[0] = new InputFilter.LengthFilter(this.mMaxInputLength);
+		p_edit_text.setFilters(filters);
 	}
 	}
 
 
 	// ===========================================================
 	// ===========================================================
@@ -164,13 +168,24 @@ public class GodotEditText extends EditText {
 	// ===========================================================
 	// ===========================================================
 	// Methods
 	// Methods
 	// ===========================================================
 	// ===========================================================
-	public void showKeyboard(String p_existing_text, int p_max_input_length) {
-		mOriginText = p_existing_text;
+	public void showKeyboard(String p_existing_text, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
+		int maxInputLength = (p_max_input_length <= 0) ? Integer.MAX_VALUE : p_max_input_length;
+		if (p_cursor_start == -1) { // cursor position not given
+			this.mOriginText = p_existing_text;
+			this.mMaxInputLength = maxInputLength;
+		} else if (p_cursor_end == -1) { // not text selection
+			this.mOriginText = p_existing_text.substring(0, p_cursor_start);
+			this.mMaxInputLength = maxInputLength - (p_existing_text.length() - p_cursor_start);
+		} else {
+			this.mOriginText = p_existing_text.substring(0, p_cursor_end);
+			this.mMaxInputLength = maxInputLength - (p_existing_text.length() - p_cursor_end);
+		}
 
 
 		final Message msg = new Message();
 		final Message msg = new Message();
 		msg.what = HANDLER_OPEN_IME_KEYBOARD;
 		msg.what = HANDLER_OPEN_IME_KEYBOARD;
 		msg.obj = this;
 		msg.obj = this;
-		msg.arg1 = p_max_input_length;
+		msg.arg1 = p_cursor_start;
+		msg.arg2 = p_cursor_end;
 		sHandler.sendMessage(msg);
 		sHandler.sendMessage(msg);
 	}
 	}
 
 

+ 10 - 0
platform/android/java/lib/src/org/godotengine/godot/input/GodotTextInputWrapper.java

@@ -53,6 +53,7 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
 	private final GodotRenderView mRenderView;
 	private final GodotRenderView mRenderView;
 	private final GodotEditText mEdit;
 	private final GodotEditText mEdit;
 	private String mOriginText;
 	private String mOriginText;
+	private boolean mHasSelection;
 
 
 	// ===========================================================
 	// ===========================================================
 	// Constructors
 	// Constructors
@@ -77,6 +78,10 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
 		mOriginText = originText;
 		mOriginText = originText;
 	}
 	}
 
 
+	public void setSelection(boolean selection) {
+		mHasSelection = selection;
+	}
+
 	// ===========================================================
 	// ===========================================================
 	// Methods for/from SuperClass/Interfaces
 	// Methods for/from SuperClass/Interfaces
 	// ===========================================================
 	// ===========================================================
@@ -95,6 +100,11 @@ public class GodotTextInputWrapper implements TextWatcher, OnEditorActionListene
 				for (int i = 0; i < count; ++i) {
 				for (int i = 0; i < count; ++i) {
 					GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, true);
 					GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, true);
 					GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, false);
 					GodotLib.key(KeyEvent.KEYCODE_DEL, KeyEvent.KEYCODE_DEL, 0, false);
+
+					if (mHasSelection) {
+						mHasSelection = false;
+						break;
+					}
 				}
 				}
 			}
 			}
 		});
 		});

+ 3 - 3
platform/android/java_godot_io_wrapper.cpp

@@ -53,7 +53,7 @@ GodotIOJavaWrapper::GodotIOJavaWrapper(JNIEnv *p_env, jobject p_godot_io_instanc
 		_get_model = p_env->GetMethodID(cls, "getModel", "()Ljava/lang/String;");
 		_get_model = p_env->GetMethodID(cls, "getModel", "()Ljava/lang/String;");
 		_get_screen_DPI = p_env->GetMethodID(cls, "getScreenDPI", "()I");
 		_get_screen_DPI = p_env->GetMethodID(cls, "getScreenDPI", "()I");
 		_get_unique_id = p_env->GetMethodID(cls, "getUniqueID", "()Ljava/lang/String;");
 		_get_unique_id = p_env->GetMethodID(cls, "getUniqueID", "()Ljava/lang/String;");
-		_show_keyboard = p_env->GetMethodID(cls, "showKeyboard", "(Ljava/lang/String;I)V");
+		_show_keyboard = p_env->GetMethodID(cls, "showKeyboard", "(Ljava/lang/String;III)V");
 		_hide_keyboard = p_env->GetMethodID(cls, "hideKeyboard", "()V");
 		_hide_keyboard = p_env->GetMethodID(cls, "hideKeyboard", "()V");
 		_set_screen_orientation = p_env->GetMethodID(cls, "setScreenOrientation", "(I)V");
 		_set_screen_orientation = p_env->GetMethodID(cls, "setScreenOrientation", "(I)V");
 		_get_screen_orientation = p_env->GetMethodID(cls, "getScreenOrientation", "()I");
 		_get_screen_orientation = p_env->GetMethodID(cls, "getScreenOrientation", "()I");
@@ -132,11 +132,11 @@ bool GodotIOJavaWrapper::has_vk() {
 	return (_show_keyboard != 0) && (_hide_keyboard != 0);
 	return (_show_keyboard != 0) && (_hide_keyboard != 0);
 }
 }
 
 
-void GodotIOJavaWrapper::show_vk(const String &p_existing, int p_max_input_length) {
+void GodotIOJavaWrapper::show_vk(const String &p_existing, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
 	if (_show_keyboard) {
 	if (_show_keyboard) {
 		JNIEnv *env = ThreadAndroid::get_env();
 		JNIEnv *env = ThreadAndroid::get_env();
 		jstring jStr = env->NewStringUTF(p_existing.utf8().get_data());
 		jstring jStr = env->NewStringUTF(p_existing.utf8().get_data());
-		env->CallVoidMethod(godot_io_instance, _show_keyboard, jStr, p_max_input_length);
+		env->CallVoidMethod(godot_io_instance, _show_keyboard, jStr, p_max_input_length, p_cursor_start, p_cursor_end);
 	}
 	}
 }
 }
 
 

+ 1 - 1
platform/android/java_godot_io_wrapper.h

@@ -70,7 +70,7 @@ public:
 	int get_screen_dpi();
 	int get_screen_dpi();
 	String get_unique_id();
 	String get_unique_id();
 	bool has_vk();
 	bool has_vk();
-	void show_vk(const String &p_existing, int p_max_input_length);
+	void show_vk(const String &p_existing, int p_max_input_length, int p_cursor_start, int p_cursor_end);
 	void hide_vk();
 	void hide_vk();
 	int get_vk_height();
 	int get_vk_height();
 	void set_vk_height(int p_height);
 	void set_vk_height(int p_height);

+ 1 - 1
platform/iphone/os_iphone.cpp

@@ -441,7 +441,7 @@ extern Error _shell_open(String p_uri);
 extern void _set_keep_screen_on(bool p_enabled);
 extern void _set_keep_screen_on(bool p_enabled);
 extern void _vibrate();
 extern void _vibrate();
 
 
-void OSIPhone::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_input_length) {
+void OSIPhone::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
 	_show_keyboard(p_existing_text);
 	_show_keyboard(p_existing_text);
 };
 };
 
 

+ 1 - 1
platform/iphone/os_iphone.h

@@ -170,7 +170,7 @@ public:
 	virtual bool can_draw() const;
 	virtual bool can_draw() const;
 
 
 	virtual bool has_virtual_keyboard() const;
 	virtual bool has_virtual_keyboard() const;
-	virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_input_length = -1);
+	virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
 	virtual void hide_virtual_keyboard();
 	virtual void hide_virtual_keyboard();
 	virtual int get_virtual_keyboard_height() const;
 	virtual int get_virtual_keyboard_height() const;
 
 

+ 1 - 1
platform/uwp/os_uwp.cpp

@@ -698,7 +698,7 @@ bool OS_UWP::has_virtual_keyboard() const {
 	return UIViewSettings::GetForCurrentView()->UserInteractionMode == UserInteractionMode::Touch;
 	return UIViewSettings::GetForCurrentView()->UserInteractionMode == UserInteractionMode::Touch;
 }
 }
 
 
-void OS_UWP::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_input_length) {
+void OS_UWP::show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_input_length, int p_cursor_start, int p_cursor_end) {
 	InputPane ^ pane = InputPane::GetForCurrentView();
 	InputPane ^ pane = InputPane::GetForCurrentView();
 	pane->TryShow();
 	pane->TryShow();
 }
 }

+ 1 - 1
platform/uwp/os_uwp.h

@@ -234,7 +234,7 @@ public:
 	virtual bool has_touchscreen_ui_hint() const;
 	virtual bool has_touchscreen_ui_hint() const;
 
 
 	virtual bool has_virtual_keyboard() const;
 	virtual bool has_virtual_keyboard() const;
-	virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_input_length = -1);
+	virtual void show_virtual_keyboard(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_input_length = -1, int p_cursor_start = -1, int p_cursor_end = -1);
 	virtual void hide_virtual_keyboard();
 	virtual void hide_virtual_keyboard();
 
 
 	virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false);
 	virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false);

+ 10 - 2
scene/gui/line_edit.cpp

@@ -119,7 +119,11 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
 			selection.doubleclick = false;
 			selection.doubleclick = false;
 
 
 			if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD)) {
 			if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD)) {
-				DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), max_length);
+				if (selection.enabled) {
+					DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), max_length, selection.begin, selection.end);
+				} else {
+					DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), max_length, cursor_pos);
+				}
 			}
 			}
 		}
 		}
 
 
@@ -918,7 +922,11 @@ void LineEdit::_notification(int p_what) {
 			}
 			}
 
 
 			if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD)) {
 			if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD)) {
-				DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), max_length);
+				if (selection.enabled) {
+					DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), max_length, selection.begin, selection.end);
+				} else {
+					DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), max_length, cursor_pos);
+				}
 			}
 			}
 
 
 		} break;
 		} break;

+ 1 - 1
servers/display_server.cpp

@@ -213,7 +213,7 @@ bool DisplayServer::is_console_visible() const {
 	return false;
 	return false;
 }
 }
 
 
-void DisplayServer::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_legth) {
+void DisplayServer::virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect, int p_max_legth, int p_cursor_start, int p_cursor_end) {
 	WARN_PRINT("Virtual keyboard not supported by this display server.");
 	WARN_PRINT("Virtual keyboard not supported by this display server.");
 }
 }
 
 

+ 1 - 1
servers/display_server.h

@@ -280,7 +280,7 @@ public:
 	virtual void console_set_visible(bool p_enabled);
 	virtual void console_set_visible(bool p_enabled);
 	virtual bool is_console_visible() const;
 	virtual bool is_console_visible() const;
 
 
-	virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_legth = -1);
+	virtual void virtual_keyboard_show(const String &p_existing_text, const Rect2 &p_screen_rect = Rect2(), int p_max_legth = -1, int p_cursor_start = -1, int p_cursor_end = -1);
 	virtual void virtual_keyboard_hide();
 	virtual void virtual_keyboard_hide();
 
 
 	// returns height of the currently shown virtual keyboard (0 if keyboard is hidden)
 	// returns height of the currently shown virtual keyboard (0 if keyboard is hidden)