From d558b07fd4d1a77581ed95ef6a7a04e0151214de Mon Sep 17 00:00:00 2001 From: Leroy Hopson Date: Wed, 3 Aug 2022 22:07:21 +1200 Subject: [PATCH] Prevent loss of focus on Tab/Arrow key press Prevents Terminal losing focus when in a scene with other inputs and the Tab or Arrow keys are pressed. Fixes #51. --- addons/godot_xterm/terminal.gd | 4 +++ test/scenes/multiple_inputs.tscn | 50 ++++++++++++++++++++++++++++++++ test/unit/terminal.test.gd | 42 +++++++++++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 test/scenes/multiple_inputs.tscn diff --git a/addons/godot_xterm/terminal.gd b/addons/godot_xterm/terminal.gd index 3868031..f5dd9dd 100644 --- a/addons/godot_xterm/terminal.gd +++ b/addons/godot_xterm/terminal.gd @@ -184,6 +184,10 @@ func _gui_input(event): ): _native_terminal.sb_reset() + # Prevent focus changing to other inputs when pressing Tab or Arrow keys. + if event.scancode in [KEY_LEFT, KEY_UP, KEY_RIGHT, KEY_DOWN, KEY_TAB]: + accept_event() + _handle_mouse_wheel(event) _handle_selection(event) diff --git a/test/scenes/multiple_inputs.tscn b/test/scenes/multiple_inputs.tscn new file mode 100644 index 0000000..c8f8bc5 --- /dev/null +++ b/test/scenes/multiple_inputs.tscn @@ -0,0 +1,50 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://addons/godot_xterm/terminal.gd" type="Script" id=1] + +[node name="HBoxContainer" type="HBoxContainer"] +anchor_right = 1.0 +anchor_bottom = 1.0 + +[node name="HBoxContainer" type="HBoxContainer" parent="."] +margin_right = 1024.0 +margin_bottom = 600.0 +size_flags_horizontal = 3 + +[node name="TextEdit" type="TextEdit" parent="HBoxContainer"] +margin_right = 338.0 +margin_bottom = 600.0 +size_flags_horizontal = 3 + +[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer"] +margin_left = 342.0 +margin_right = 681.0 +margin_bottom = 600.0 +size_flags_horizontal = 3 + +[node name="TextEdit3" type="TextEdit" parent="HBoxContainer/VBoxContainer"] +margin_right = 339.0 +margin_bottom = 197.0 +size_flags_vertical = 3 + +[node name="Terminal" type="Control" parent="HBoxContainer/VBoxContainer"] +margin_top = 201.0 +margin_right = 339.0 +margin_bottom = 398.0 +focus_mode = 2 +size_flags_vertical = 3 +script = ExtResource( 1 ) + +[node name="TextEdit2" type="TextEdit" parent="HBoxContainer/VBoxContainer"] +margin_top = 402.0 +margin_right = 339.0 +margin_bottom = 600.0 +size_flags_vertical = 3 + +[node name="TextEdit2" type="TextEdit" parent="HBoxContainer"] +margin_left = 685.0 +margin_right = 1024.0 +margin_bottom = 600.0 +size_flags_horizontal = 3 + +[connection signal="data_sent" from="HBoxContainer/VBoxContainer/Terminal" to="HBoxContainer/VBoxContainer/Terminal" method="write"] diff --git a/test/unit/terminal.test.gd b/test/unit/terminal.test.gd index a0b0cf8..79116fa 100644 --- a/test/unit/terminal.test.gd +++ b/test/unit/terminal.test.gd @@ -31,3 +31,45 @@ func test_bell_cooldown() -> void: term.write("\a") yield(yield_to(term, "bell", 5), YIELD) assert_signal_emit_count(term, "bell", 2) + + +class TestMultipleInputs: + # Tests for when Terminal is around other input nodes and arrow keys or TAB + # key is pressed. Focus should not change to other inputs when pressing these + # keys (same behaviour as TextEdit node). + # See: https://github.com/lihop/godot-xterm/issues/51 + extends "res://addons/gut/test.gd" + + const KEYS := { + KEY_LEFT = KEY_LEFT, + KEY_UP = KEY_UP, + KEY_RIGHT = KEY_RIGHT, + KEY_DOWN = KEY_DOWN, + KEY_TAB = KEY_TAB, + } + + var terminal: Control + + func press_key(scancode: int, unicode := 0) -> void: + var key_down = InputEventKey.new() + key_down.scancode = scancode + key_down.pressed = true + Input.parse_input_event(key_down) + yield(get_tree().create_timer(0.1), "timeout") + var key_up = InputEventKey.new() + key_up.scancode = scancode + key_up.pressed = false + Input.parse_input_event(key_up) + + func before_each(): + var scene := preload("../scenes/multiple_inputs.tscn").instance() + add_child_autofree(scene) + terminal = scene.find_node("Terminal") + terminal.grab_focus() + + func test_terminal_keeps_focus_when_certain_keys_pressed(): + for key in KEYS.keys(): + press_key(KEYS[key]) + assert_true( + terminal.has_focus(), "Terminal should still have focus after %s is pressed." % key + )