godot: LineEdit and TextEdit do not accept input events entering text, causing them to pass to unhandled.

Godot version: 8b0ad17b760b6cc803edc815fe65f8de1d92bf74

OS/device including version: OS X El Capitan 10.11.6

Issue description: LineEdit and TextEdit don’t seem to correctly do accept_event() on input events that actually enter text into them (input events like backspace to clear text are fine though!), as such, they pass through to unhandled input which isn’t ideal.

I should, the enter key to enter text also has this issue, but that one seems like a really easy fix, because it’s doing a return before the accept_event() call.

I tried to look into this but they’re still calling accept_event(), so I have absolutely no idea why the events are being passed to unhandled.

Steps to reproduce:

  1. Type into a LineEdit
  2. See unhandled input go off everywhere.

Minimal reproduction project: Unhandled LineEdit Input.zip

  • I searched the existing GitHub issues for potential duplicates.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 8
  • Comments: 17 (9 by maintainers)

Most upvoted comments

Can confirm in 3.2.1. I moved the movement input of my player character into _unhandled_input just so I could prevent that the player moves when he’s typing in that chat. It didn’t work at first, and I had to do a work-around.

Though, when I was doing a “teleport to home base” hotkey, that was written in an _unhandled_input function, I noticed that it didn’t teleport the player when I was typing in the key in a LineEdit. It appears that when I type the character in the LineEdit, it would pass the InputEvent to _unhandled_input with pressed set to false.

@jrockett6 I would’ve thought so, except for the second point, which was kind of strange IMO - don’t have an MVCE or repro steps though

In Godot 4 this is working as intended on Mac OS.

However, it’s not clear to me what the intended workflow is for when you are working with input polling as these are not handled:

Note: Input’s methods reflect the global input state and are not affected by Control.accept_event or Viewport.set_input_as_handled, as those methods only deal with the way input is propagated in the SceneTree.

which is the commonly recommended workflow for handling movement code, where simultaneous inputs need to be polled.

Is there an appropriate workaround that exists? Either limiting the Input singleton to unhandled events or polling for actions simultaneously in the scene tree input propogation?

Edit: I guess it is possible to update a persistent direction variable on any press/release inside of unhandled_input, which is a fine workaround.

Edit: It is slightly more complicated than the above, as only the pressed actions are handled by the focused LineEdit. So you have to do a bit of extra manual work to keep track of button presses your movement code. E.g. with this psudocode in _unhandled_input:

        if event.is_action_pressed("move_up") {
            self.direction.y += 1.0;
        } else if event.is_action_released("move_up") {
            self.direction.y -= 1.0;
        }

the direction will still be affected by the released calls while focus is in the LineEdit.

I can confirm the bug here.

_unhandled_input will fire on inputevents received by LineEdit.

This makes it incredibly difficult to lets say: Have Enter open a chat interface and focus its LineEdit. Then hide and release focus of said interface when the user presses Enter again to send their message.

Because what will happen is that the message will be sent you hide and release focus, then _unhandled_input fires and you immediately require focus.

After encountering this issue and reading LineEdit.cpp I subclassed LineEdit to “short circuit” and catch desired input. I put it here firstly so that other people finding this issue can get a quick solution and secondly to generate discussion on whether behaviour similar to but not identical to this should be implemented in godot by amending LineEdit._gui_input() and perhaps implementing LineEdit._input() if necessary.

extends LineEdit
class_name SafeLineEdit

func _input(event):
	if (has_focus() && is_editable() && event is InputEventKey 
		and event.unicode >= 32 and event.scancode != KEY_DELETE):
		_gui_input(event)
		accept_event()