Repository: godot
Issue: Problems with LineEdit and TextEdit on android.
Labels: bug,platform:android,topic:porting,usability,topic:input,topic:gui

### Godot version

3.x, 4.x

### System information

Android

### Issue description

>**Note:** `TextEdit` is a Node from Godot, while `EditText` is a native UI element from Android.

When I tried out the Android Editor I was quite annoyed by the fact, that the Home / End keys were not working and so I had a look at the code in a hope to fix it.

Sadly there are many problems with input in `Line/TextEdits` on Android which are all interconnected in a way, that I cannot solve them with my limited knowledge of the Godot code base.
This Issue is meant to document my findings and considerations to help others who might try to solve this problem.

The reason for all the problems which occur is, that on android an `EditText` is used to get the input from the virtual keyboard. When disabling this edit text everything works as expected (this is off course not a solution because it only works with a hardware keyboard).

### 1. End / Home keys Page Up / Down keys
The mentioned keys do not work on android.

[Here](https://github.com/godotengine/godot/blob/f814e15c7f60a685e8b3623fc93231c18ccd3627/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java#L227) some keys are send to the Godot engine while others are send to the `EditText`. The method `needHandlingInGodot` does the filtering and should send the home, end, page up and page down keys to Godot as well. (This is not a solution as it wont solve 3.)

### 2. Soft keyboard cursor movement not handled
Nowadays there are ways to change the cursor position with a soft keyboard without having to touch the `EditText`. On Samsung for example one keeps the space key pressed and can then move the cursor position.

This is not forwarded to godot. [This](https://stackoverflow.com/questions/5962366/android-edittext-listener-for-cursor-position-change) post could be a good starting point to do it.

### 3. Cursor position not in Sync
Above I stated, that the home and end keys don't work nor do the soft keyboard cursor movements. But that is only half of the truth. Those keys are processed by Android and therefore they change the cursor position in the `EditText` but not in Godot.
On the other hand the arrow keys are send to Godot and change the cursor position in there but not in Android. This leads to different cursor positions in Godot and in Android.

To solve this some events could be sent to Godot and Android to keep the cursor position in sync. An other option would be to overwrite `onSelectionChanged` as proposed in 2. In that case all cursor movements would be handled by android first and then afterwards the new cursor position would be send to Godot. (This is no solution as it does not fix 4.)

### 4. Page Up / Down keys ...again
Even if somehow the Page Up and Down keys were handled by Godot and Android this would still lead to different cursor positions as the amount of lines jumped depends on the visible lines. And I do not think it is feasible to synchronize the amount of lines shown in Godot to the style of the `EditText`.

A solution would be to let Godot process all incoming events and then just sync the `EditText`.

### 5. Soft keyboard suggestions
This results from 3.
The suggestions presented to the user are based on the Android cursor position and therefore do not always match the Godot cursor position.

### 6. Cannot delete text
This results from 3.

Example:
- The Android cursor is at position 1 of the string `"Hello World"`
- The Godot cursor is at the end
- the user presses delete
- the string is now `"Hello Worl"` and the Godot cursor is still at the end
- the android cursor is at position 0
- the user presses delete
- nothing happens, as there is no char left to be deleted in the `EditText`

### 7. Cannot delete tab (content not in sync)
[Here](https://github.com/godotengine/godot/blob/f814e15c7f60a685e8b3623fc93231c18ccd3627/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java#L232) the tab key is send to Godot. Therefore it is not handled by Android. When pressing tab in an empty `Line/TextEdit` and then trying to delete it nothing happens as there is nothing to be deleted in the `EditText`.

For some reason deleting tabs in the code editor works. But but it does not in other fields like the inspector.

> **Hint:** For users of the Godot Android editor who stumble in any of those "not in sync" problems. Try tapping or clicking on the `Line/TextEdit` at your cursor position. This will synchronize content and cursor position as Godot sends its own state to Android when trying to open the soft keyboard.

### 8. Content not in sync
When clicking on a spot in a `Line/TextEdit` Godot will try to open the virtual keyboard. When this is done the content of the `EditText` gets updated. But for some reason only the content before the cursor position gets inserted into the `EditText`. The code may be from a time when cursor movement without tapping was not considered. This could lead to desynchronized cursor position even if all input was handled by Godot and Android.

A possible fix:
In [this](https://github.com/godotengine/godot/blob/master/platform/android/java/lib/src/org/godotengine/godot/input/GodotEditText.java#L129) file change:
```
if (msg.arg2 != -1) {
    edit.setSelection(msg.arg1, msg.arg2);
    edit.mInputWrapper.setSelection(true);
} else {
    edit.mInputWrapper.setSelection(false);
}
```
to:
```
if (msg.arg2 != -1) {
    edit.setSelection(msg.arg1, msg.arg2);
    edit.mInputWrapper.setSelection(true);
} else {
    edit.setSelection(msg.arg1);
    edit.mInputWrapper.setSelection(false);
}
```
And change line 245 and 248 to: `this.mOriginText = p_existing_text;`
>**Note:** This fix does not consider the max line length.

### 9. Confirming and cancelling input
Related to #59703.
In the desktop editor you can press Enter to confirm input at some places while you can press Escape to cancel it. This is not possible in the android editor.

### 10. Backspace
The backspace key does not seem to work. Though I'm not quite sure whether it is not processed or only processed by Android.


## Solutions
I think the list above shows how bug prone the current system is, as there is no clear source of truth. Even if the mentioned problems would be solved in some way I probably missed some other issues. And new ones could come up with every change to behaviour on either side.

My first suggestion is to set the visibility of the `EditText` to `View.GONE` whenever a physical keyboard is connected to the device. While this is no solution for the described problems it means, that the soft keyboard will never be shown and Godot just uses the incoming events as it would on a desktop platform. This would improve the usability of the Android Editor because everything should work like on desktop.

Besides that the problems from above should be fixed as well. The best solution which I could come up with would be to intercept all input that goes to the `EditText` and send it to Godot. Then whenever something changes syncing the `EditText` to Godot.
Possible problem with that would be, that the suggestions of the soft keyboard could flicker.
Also I don't think this is possible without changing platform independent code as there is no way or reason for Godot to communicate its current state to Android. It only passively listens for events.

### Steps to reproduce

See above.

### Minimal reproduction project

Android Editor is sufficient.