OverviewFilesCommitsIssuesDocsReleasesPeers

godot-keet / scripts / chat_input.gd

65 lines · gd ref:
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()