Stabilize custom and Android text entry

This commit is contained in:
Alexander Sellite 2026-08-16 17:57:12 -04:00
parent 1aa77180a4
commit 5df8b2e7cc
2 changed files with 288 additions and 30 deletions

View file

@ -21,6 +21,14 @@ class ControllerInputProbe:
pressed_buttons.append(button.button_index)
class NativeKeyboardProbe:
extends OnScreenKeyboard
func _uses_native_virtual_keyboard() -> bool:
return true
func _initialize() -> void:
call_deferred("_run")
@ -29,6 +37,7 @@ func _run() -> void:
_validate_default_and_persistence()
await _validate_keyboard_entry()
await _validate_automapped_face_buttons()
await _validate_native_keyboard()
print("On-screen keyboard validation: PASS")
quit()
@ -48,6 +57,21 @@ func _validate_default_and_persistence() -> void:
assert(
KeyboardType.should_enable_for_controller(true, true, "Android")
)
assert(
KeyboardType.should_use_native_virtual_keyboard(
false, true, "Android"
)
)
assert(
not KeyboardType.should_use_native_virtual_keyboard(
true, true, "Android"
)
)
assert(
not KeyboardType.should_use_native_virtual_keyboard(
false, true, "Linux"
)
)
var manager := SettingsManagerType.new()
root.add_child(manager)
assert(manager.load_settings())
@ -91,7 +115,9 @@ func _validate_keyboard_entry() -> void:
assert(edit.caret_column == edit.text.length())
assert(keyboard.get("_buffer_caret") == edit.text.length())
assert(
str((keyboard.get("_preview") as Label).text).begins_with("seed")
str(
(keyboard.get("_preview") as RichTextLabel).get_parsed_text()
).begins_with("seed")
)
var left_page_event := InputEventJoypadButton.new()
left_page_event.button_index = JOY_BUTTON_LEFT_SHOULDER
@ -109,13 +135,21 @@ func _validate_keyboard_entry() -> void:
await process_frame
var focused_key := root.gui_get_focus_owner() as Button
assert(focused_key != null and focused_key.text == "q")
var second_key := keyboard.get("_key_buttons")[1] as Button
second_key.grab_focus()
var outside_button := Button.new()
host.add_child(outside_button)
outside_button.grab_focus()
assert(root.gui_get_focus_owner() == outside_button)
keyboard.call("_process", 0.0)
assert(root.gui_get_focus_owner() == second_key)
var conflicting_cancel_binding := InputEventJoypadButton.new()
conflicting_cancel_binding.button_index = JOY_BUTTON_A
InputMap.action_add_event(&"ui_cancel", conflicting_cancel_binding)
keyboard.call("_input", activate_event)
InputMap.action_erase_event(&"ui_cancel", conflicting_cancel_binding)
assert(keyboard.is_open())
assert(edit.text == "seedq")
assert(edit.text == "seedw")
var left_trigger := InputEventJoypadMotion.new()
left_trigger.axis = JOY_AXIS_TRIGGER_LEFT
left_trigger.axis_value = 1.0
@ -126,20 +160,23 @@ func _validate_keyboard_entry() -> void:
right_trigger.axis_value = 1.0
keyboard.call("_input", right_trigger)
assert(keyboard.get("_buffer_caret") == edit.text.length())
var preview := keyboard.get("_preview") as RichTextLabel
var preview_height_before_blink: float = preview.get_content_height()
var preview_text_before_blink: String = preview.get_parsed_text()
keyboard.call("_process", KeyboardType.CARET_BLINK_INTERVAL)
assert(
not str((keyboard.get("_preview") as Label).text).contains(
KeyboardType.CARET_GLYPH
)
not bool(keyboard.get("_caret_visible"))
)
assert(preview.get_parsed_text() == preview_text_before_blink)
assert(is_equal_approx(preview.get_content_height(), preview_height_before_blink))
keyboard.call("_type_character", "a")
keyboard.call("_type_space")
keyboard.call("_set_page", KeyboardType.Page.UPPER)
keyboard.call("_type_character", "B")
assert(edit.text == "seedqa B")
assert(edit.text == "seedwa B")
keyboard.call("_move_caret", -1)
keyboard.call("_type_character", "C")
assert(edit.text == "seedqa CB")
assert(edit.text == "seedwa CB")
var input_probe := ControllerInputProbe.new()
root.add_child(input_probe)
root.move_child(input_probe, 0)
@ -148,7 +185,7 @@ func _validate_keyboard_entry() -> void:
backspace_event.pressed = true
Input.parse_input_event(backspace_event)
await process_frame
assert(edit.text == "seedqa B")
assert(edit.text == "seedwa B")
assert(input_probe.pressed_buttons.is_empty())
var close_event := InputEventJoypadButton.new()
close_event.button_index = JOY_BUTTON_B
@ -166,7 +203,28 @@ func _validate_keyboard_entry() -> void:
)
keyboard.call("_submit")
assert(not keyboard.is_open())
assert(submitted == ["seedqa B"])
assert(submitted == ["seedwa B"])
var letter_body := TextEdit.new()
letter_body.text = "letter"
letter_body.focus_mode = Control.FOCUS_ALL
host.add_child(letter_body)
letter_body.text_changed.connect(func() -> void:
outside_button.call_deferred("grab_focus")
)
letter_body.grab_focus()
keyboard.call("_input", activate_event)
assert(keyboard.is_open())
for _frame: int in 2:
await process_frame
var letter_key := keyboard.get("_key_buttons")[2] as Button
letter_key.grab_focus()
keyboard.call("_input", activate_event)
for _frame: int in 2:
await process_frame
assert(letter_body.text == "lettere")
assert(root.gui_get_focus_owner() == letter_key)
keyboard.call("_input", close_event)
assert(not keyboard.is_open())
host.queue_free()
@ -220,3 +278,51 @@ func _validate_automapped_face_buttons() -> void:
assert(not keyboard.is_open())
host.queue_free()
manager.queue_free()
func _validate_native_keyboard() -> void:
var host := Control.new()
root.add_child(host)
var edit := LineEdit.new()
edit.focus_mode = Control.FOCUS_ALL
edit.virtual_keyboard_enabled = true
host.add_child(edit)
var outside_button := Button.new()
host.add_child(outside_button)
var keyboard := NativeKeyboardProbe.new()
host.add_child(keyboard)
await process_frame
edit.grab_focus()
assert(keyboard.is_open())
var character_event := InputEventKey.new()
character_event.keycode = KEY_A
character_event.unicode = 97
character_event.pressed = true
keyboard.call("_input", character_event)
outside_button.grab_focus()
await process_frame
assert(edit.has_focus())
var backspace_event := InputEventKey.new()
backspace_event.keycode = KEY_BACKSPACE
backspace_event.pressed = true
keyboard.call("_input", backspace_event)
outside_button.grab_focus()
await process_frame
assert(edit.has_focus())
var close_event := InputEventJoypadButton.new()
close_event.button_index = JOY_BUTTON_B
close_event.pressed = true
keyboard.call("_input", close_event)
assert(not edit.has_focus())
assert(not keyboard.is_open())
assert(keyboard.request_for_control(edit))
await process_frame
assert(edit.has_focus())
assert(keyboard.is_open())
var escape_event := InputEventKey.new()
escape_event.keycode = KEY_ESCAPE
escape_event.pressed = true
keyboard.call("_input", escape_event)
assert(not edit.has_focus())
assert(not keyboard.is_open())
host.queue_free()