Keep arrow keys in active text fields (#132)
This commit is contained in:
parent
26b5b5d62f
commit
bfbcba7109
2 changed files with 70 additions and 0 deletions
|
|
@ -198,6 +198,40 @@ func _run() -> void:
|
|||
standard_button.get_theme_stylebox("hover") == old_hover_style,
|
||||
"mouse hover styling was not restored after controller use",
|
||||
)
|
||||
var text_entry := LineEdit.new()
|
||||
text_entry.position = Vector2(520.0, 60.0)
|
||||
text_entry.size = Vector2(220.0, 48.0)
|
||||
text_entry.text = "editable text"
|
||||
stage.add_child(text_entry)
|
||||
standard_button.grab_focus()
|
||||
await process_frame
|
||||
presentation.call("_neutralize_current_navigation_focus")
|
||||
text_entry.grab_focus()
|
||||
await process_frame
|
||||
_expect(
|
||||
presentation.get("_neutral_focus_seed") == null,
|
||||
"entering a text field leaves the prior menu focus seed armed",
|
||||
)
|
||||
for keycode: Key in [KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN]:
|
||||
var arrow_key := InputEventKey.new()
|
||||
arrow_key.keycode = keycode
|
||||
arrow_key.physical_keycode = keycode
|
||||
arrow_key.pressed = true
|
||||
presentation._input(arrow_key)
|
||||
_expect(
|
||||
root.gui_get_focus_owner() == text_entry,
|
||||
"arrow key %s pulled focus out of an active text field" % keycode,
|
||||
)
|
||||
var modified_arrow := InputEventKey.new()
|
||||
modified_arrow.keycode = KEY_LEFT
|
||||
modified_arrow.physical_keycode = KEY_LEFT
|
||||
modified_arrow.shift_pressed = true
|
||||
modified_arrow.pressed = true
|
||||
presentation._input(modified_arrow)
|
||||
_expect(
|
||||
root.gui_get_focus_owner() == text_entry,
|
||||
"a modified arrow pulled focus out of an active text field",
|
||||
)
|
||||
var item_list := ItemList.new()
|
||||
item_list.position = Vector2(80.0, 160.0)
|
||||
item_list.size = Vector2(240.0, 150.0)
|
||||
|
|
|
|||
|
|
@ -86,6 +86,15 @@ func _input(event: InputEvent) -> void:
|
|||
event is InputEventJoypadButton or event is InputEventJoypadMotion
|
||||
):
|
||||
return
|
||||
# Physical keyboard arrows belong to an active text editor. A mouse click can
|
||||
# leave the previously focused menu button cached as the neutral controller
|
||||
# seed; restoring that seed here would pull focus out of the editor before
|
||||
# LineEdit/TextEdit can move its caret or selection.
|
||||
if _keyboard_direction_belongs_to_text_entry(event):
|
||||
_navigation_focus_active = false
|
||||
_neutral_focus_seed = null
|
||||
_set_controller_active(false)
|
||||
return
|
||||
var directional_navigation: bool = _is_directional_navigation(event)
|
||||
if directional_navigation:
|
||||
_directional_input_generation += 1
|
||||
|
|
@ -217,6 +226,11 @@ func _on_focus_changed(control: Control) -> void:
|
|||
if _directional_input_in_flight and _is_navigation_focus(control):
|
||||
_navigation_focus_active = true
|
||||
_neutral_focus_seed = null
|
||||
elif not _is_navigation_focus(control):
|
||||
# Text entry supersedes any button remembered before the field was clicked.
|
||||
# Keeping that seed would make the next keyboard arrow restore the button.
|
||||
_navigation_focus_active = false
|
||||
_neutral_focus_seed = null
|
||||
elif not _navigation_focus_active and _is_navigation_focus(control):
|
||||
_capture_neutral_focus_seed(control)
|
||||
return
|
||||
|
|
@ -261,6 +275,28 @@ func _is_directional_navigation(event: InputEvent) -> bool:
|
|||
)
|
||||
|
||||
|
||||
func _keyboard_direction_belongs_to_text_entry(event: InputEvent) -> bool:
|
||||
var key_event := event as InputEventKey
|
||||
if key_event == null or not key_event.pressed:
|
||||
return false
|
||||
var focus_owner: Control = _active_focus_owner()
|
||||
if not (focus_owner is LineEdit or focus_owner is TextEdit):
|
||||
return false
|
||||
# Check the keycodes directly as well as the built-in actions so modified
|
||||
# editing gestures such as Shift+Left and Ctrl+Right cannot be mistaken for
|
||||
# menu navigation when action matching requires exact modifier parity.
|
||||
if key_event.keycode in [KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN]:
|
||||
return true
|
||||
if key_event.physical_keycode in [KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN]:
|
||||
return true
|
||||
return (
|
||||
event.is_action_pressed(&"ui_left")
|
||||
or event.is_action_pressed(&"ui_right")
|
||||
or event.is_action_pressed(&"ui_up")
|
||||
or event.is_action_pressed(&"ui_down")
|
||||
)
|
||||
|
||||
|
||||
func _is_navigation_focus(control: Control) -> bool:
|
||||
# Text entry is an explicit interaction rather than menu navigation. It must
|
||||
# retain direct focus for typing, including Chat and dialog fields.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue