extends TextEdit
## Chat input: Enter sends, Shift+Enter inserts newline.
##
## The C++ TextEdit handler checks is_action("ui_text_newline") and inserts
## a newline BEFORE any GDScript _gui_input() can prevent it. No amount of
## accept_event() or set_input_as_handled() can stop it.
##
## Solution: remap the InputMap so bare Enter is NOT in ui_text_newline.
## Only Shift+Enter triggers ui_text_newline (newline insertion).
## Then our _gui_input() catches bare Enter and emits submit_pressed.
signal submit_pressed
var _saved_events: Array = []
func _ready() -> void:
focus_entered.connect(_remap_enter)
focus_exited.connect(_restore_enter)
print("[chat_input] InputMap remap approach ready")
func _remap_enter() -> void:
# Save original ui_text_newline events
_saved_events = InputMap.action_get_events("ui_text_newline").duplicate()
# Clear all events from ui_text_newline
InputMap.action_erase_events("ui_text_newline")
# Re-add ONLY Shift+Enter as the newline trigger
var shift_enter := InputEventKey.new()
shift_enter.keycode = KEY_ENTER
shift_enter.shift_pressed = true
InputMap.action_add_event("ui_text_newline", shift_enter)
var shift_kp_enter := InputEventKey.new()
shift_kp_enter.keycode = KEY_KP_ENTER
shift_kp_enter.shift_pressed = true
InputMap.action_add_event("ui_text_newline", shift_kp_enter)
func _restore_enter() -> void:
# Restore original InputMap events
InputMap.action_erase_events("ui_text_newline")
for ev: Variant in _saved_events:
if ev is InputEvent:
InputMap.action_add_event("ui_text_newline", ev)
_saved_events.clear()
func _gui_input(event: InputEvent) -> void:
if event is InputEventKey and event.pressed and not event.echo:
if event.keycode == KEY_ENTER or event.keycode == KEY_KP_ENTER:
if not event.shift_pressed:
# C++ handler didn't fire (Enter removed from ui_text_newline)
# No newline inserted. Emit submit.
accept_event()
submit_pressed.emit()
func _exit_tree() -> void:
# Safety: restore InputMap if node is removed while focused
if _saved_events.size() > 0:
_restore_enter()