TextField ignores key input when Focus() is used

Hello,
we are encountering a very strange bug since we upgraded to Unity 2022.2.6f1 (from 2022.1.24f1) on Windows in the UI Elements system:

When a TextField is clicked in our UI for the first time, the first key press is ignored by the text field, only the second and further keypresses are actually registered and change the contents of the field.

Debugging this, we tracked this down to be caused by using textField.Focus() - which we kind of need for our UI to work as intended.

However, searching on google, the forums and the known issues list we could not find anyone reporting an even remotely similar issue.
Is there a bug report for this already, are we using something wrong, or has genuinely no one else encountered this yet?

Of course we tested that this is not caused by our own code doing something wrong, but no, it happens in a minimal reproduction project without any of our custom code as well.

I have attached the minimal repro.
Using that project the bug can be observed using these steps:

  1. Load project and open the “FocusRepro” scene directly in the Assets folder
  2. Start play mode
    A:
  3. The script in the scene automatically focuses the first text field in Start(), so just press any key now, watch it get ignored and then press again to finally see input show up.

B:
4) Un-focus the text field, Click the button in the scene
5) Type something. To make things even weirder, it works fine in this case (the Focus() call comes from the onClick event of the button)

Something we noticed in the UI Event debugger when trying to figure out what is going on is that the first key-press event is not sent to the text field, but to the UiDocument’s root element:

For completeness sake i am putting the code of the Start() method here aswell:

void Start() {
        uiDocument = GetComponent<UIDocument>();

        var textInput = uiDocument.rootVisualElement.Q<TextField>("CustomInput");
        var button = uiDocument.rootVisualElement.Q<Button>();
       
        textInput.RegisterCallback<ChangeEvent<string>>(
            changed => {
                Debug.Log($"Got change event : {changed.newValue}");
            });
           
        //!!! This breaks inputs
        textInput.Focus();
       
        button.clicked += () =>
        {
            Debug.Log("Clicked button");
            //!!! But somehow it works as expected from here?
            textInput.Focus();
        };
    }

8986825–1236973–FocusBugRepro.zip (28.4 KB)

2 Likes

Hi,

Can you please report this bug inside Unity via the menu “Help > Report a bug” ?

Thanks.

This seems to be similar/identical with https://issuetracker.unity3d.com/issues/input-field-ignores-first-keyboard-input-when-calling-focus-from-code

Same here: Unity 2022.2.19
The ticket is open since around 2 Months now…
Are there any workarounds known?

It looks its not a problem with the TextBox, its a problem with focus. Even when adding own keyDown handlers, they not fire at the first time after the focus.

No unfortunately we havent found a workaround either. Hopefully Unity will fix it soon

1 Like

Hi,
would be possible to maybe get an update on this problem? The page in the public issue tracker contains barely any info for when to expect a fix, and the “private” issue i created was closed due to being a duplicate of the public issue.

Still no response…

Issue tracker says it was fixed in 2022.3.8f1, 2023.1.10F1
https://issuetracker.unity3d.com/is…treeview-is-focused-only-during-a-mouse-click

That sounds like a different bug, but ill try the new versions, thank you for the other issue link!

After testing, that is definitely a different bug. I can still reproduce the issue from the first post with both of the new versions.
Pretty disappointing after waiting 4 days for those versions to finally show up in the Hub.

1 Like

Hi BIIWilhelmSchnepp. I’ve reproduced your issue and it’s indeed pretty nasty. No workarounds that don’t involve pretty ugly hacks. Had you reported it already? If it was linked to the wrong issue, you might need to report it again, as there seems to be no link to your project anywhere in the bug’s page. Also I agree it looks like a very different bug.

I think Mavericks first posted issue seems the one looks more fitting. Isn’t that the one from this thread?

Hi @uBenoitA , the issue that was linked in this post
[1] TextField ignores key input when Focus() is used
is accurately describing the issue, and that is still open.

But @Maverick also linked to a different issue saying the bug may may be fixed in post
[2] TextField ignores key input when Focus() is used
But that issue and fix seem to be unrelated as my bug is still occuring with the versions linked there.

The bug report for this issue
[3] https://issuetracker.unity3d.com/issues/input-field-ignores-first-keyboard-input-when-calling-focus-from-code .
was not created by me, but this forum thread is linked in the comments.
I also initially created another bug report in some private issue tracker (presumably through our organization, not sure!?) that was quickly closed as a duplicate of the issue on the public tracker ([3]).

1 Like

Hey @antoine-unity @uBenoitA ,
is there any update on this bug?
This has been open for over 5 months now, without any meaningful information on when it will be fixed, and the bug is really annoying and very hard to work around on the code side.

If needed i am happy to provide even more details, but i think the reproduce-me in the first post should be more than enough to fix the issue.

1 Like

Its pretty horrible. Can everyone here upvote the issue, so the devs might see it?

Its killing one of the basic Usability features, when clicking a button to open something the searchbar inside is focused and the player can directly type to start searching. Its pretty horrible, that he first need to click in the text field with the mouse…

Did anyone found a workaround for this issue?

1 Like

Yes, we have found a workaround for the issue. The following code is specifically for TextFields, but you may be able to adapt it for other Focusable Elements. If you find a more generic solution, please let me know! This fix is currently in its first iteration, we may find a better solution.

Since it uses reflection, I should note that we use Unity 2022.2.6f1. The method names may change with different versions.

Furthermore, we use a different logging library, but you can easily adjust the non-compiling Logging Code to use the Unity Logging functions.

public class TextElementFocusWorkaround : MonoBehaviour
    {
        private const string executeDefaultEventMethodName = "ExecuteDefaultActionAtTarget";
       
        [SerializeField]
        private UIDocument _document;
       
        private void Start() {
            // To fix the bug, one has to first think like the bug!
            // When using the event debugger in unity, you will find that the first key down event is sent to the root.
            // BUT this is not the rootVisualElement of the document, that would be too easy.
            // It is the rootVisualElement of the 'Panel', which always seems to be the one element with no parent.
            var absoluteRoot = _document.rootVisualElement;
            while(absoluteRoot.parent != null)
                absoluteRoot = absoluteRoot.parent;
           
            absoluteRoot.RegisterCallback<KeyDownEvent>(evt => {
                // When this root receives an event, we have special code to handle the
                // bug for TextFields, where this bug is at its worst.
                if (evt.target == absoluteRoot && absoluteRoot.focusController.focusedElement is TextField focusedText) {
                   
                    // Now we want to send the event that mistakenly arrived in the root to the proper target.
                    // As detailed before, all attempts at manually re-sending the event failed.
                    // Thus we directly call the internal method that handles the event.
                    // Interestingly, this internal method is on the TextElement, a child of the TextField
                   
                    var underlyingTextElement = focusedText.Q<TextElement>();
                    if (underlyingTextElement == null) {
                        Log.Warning("Text Field Focus Workaround not working: Could not find a TextElement beneath {0}! "
                            + "This is non-critical, but may require the user to type a key twice",
                            focusedText
                        );
                        return;
                    }
                   
                    evt.target = underlyingTextElement;
                   
                    // And reflection is the only way to call this method, which
                    // subsequently hands off the event to its Sub-EventHandlers
                   
                    var executeDefaultEventActionMethod = typeof(TextElement).GetMethod(
                        executeDefaultEventMethodName,
                        BindingFlags.NonPublic | BindingFlags.Instance
                    );
                   
                    if (executeDefaultEventActionMethod == null) {
                        Log.Warning("Text Field Focus Workaround not working: Could not find method {0}! "
                            + "This is non-critical, but may require the user to type a key twice",
                            executeDefaultEventMethodName
                        );
                        return;
                    }

                   
                    var textFieldValueBefore = focusedText.value;
                   
                    executeDefaultEventActionMethod.Invoke(underlyingTextElement, new object[] { evt });
                   
                    var textFieldValueAfter = focusedText.value;
                   
                    Log.Information(
                        "Applied Text Field Focus Workaround for KeyDown Character {0}: \"{1}\" -> \"{2}\"",
                        evt.character, textFieldValueBefore, textFieldValueAfter
                    );
                }
            });
           
        }
    }
1 Like