Unity Editor: Replicate a Ctrl+A behavior for text fields

As Unity's Editor GUI doesn't natively provide a way to select all text of a focused text field/area and because it's not that trivial to create such behavior yourself, I thought I might share my solution for that behavior, as it's pretty reliable, but also requires a bit of a setup at first.

The basic idea is to take away the focus of the field (to blur it) and then refocus it on the next OnGUI() call when the desired shortcut is pressed. This leads to the whole text of the text-field/-area to be selected. For that, we need to give the GUI control a name and then reference it via the name on the next call.

To show you how this is done, here is a quick and broken down example showing just that:

private string name;
private bool nameInputBlurred, nameInputFocused;

private void OnGUI()
{
  Event evt = Event.current;

  //check if the text field is currently in focus (with the name we gave it on the previous OnGUI() calls)
  nameInputFocused = GUI.GetNameOfFocusedControl() == "NameInput"
  
  //give the following GUI control a specific name to reference it later
  GUI.SetNextControlName("NameInput");
  name = GUILayout.TextField(name);

  //select the whole text in the currently active text field by re-focussing the field
  if (nameInputBlurred)
  {
    GUI.FocusControl("NameInput");
    nameInputBlurred = false;
  }

  //temporarily remove focus from the name-input text field
  if (nameInputFocused && evt.control && evt.keyCode == KeyCode.A && evt.type == EventType.KeyUp)
  {
    GUIUtility.keyboardControl = 0;
    evt.Use();

    //keep track of whether the input has been blurred
    nameInputBlurred = true;
  }
}

It's a bit mind-bending that the actual logic is only valid after at least one run-through of the OnGUI() function, because the GUILayout.TextField() has no name assigned initially.

Let's recap what's happening here:

  1. First, we check if the currently focused control is the one we named "NameInput" and store that in the nameInputFocused boolean;

  2. We only then create the actual text field and precede it with GUI.SetNextControlName(), which assigns a custom name to any GUI or GUILayout control, which allows us to reference it later (like giving it a tag);

  3. Then we check if the input has been blurred before (another thing we only do in the previous OnGUI() calls and declare later on), which if true, re-focuses the text field and because of Unity's default behavior selects all the content in the text field/area - we also set the nameInputBlurred back to false to make this a one-time deal

  4. Now we define the logic for blurring any input control by setting the keyboardControl to 0, but only IF the name input is currently in focus and our desired keyboard shortcut is being pressed (in this case Ctrl+A), and then check for the KeyUp event type makes sure, that this doesn't fire on every call, but only when we release the shortcut

    1. We then eat/use the current event to make sure that no other event-related logic that follows during this OnGUI() call is being processed to prevent undesired behaviors

    2. At last, we also store that the input has been blurred, to notify the next OnGUI() call that the input should be blurred immediately afterward

It might seem a bit intimidating at first, but once you got the basic understanding of what's going and outsource some of the code to external functions like the code for blurring the current event's focus or maybe even the whole thing as a custom GUI control you can easily replicate this behavior in your own editors and add a bit more of the functionality that Unity is missing by default and that we've come to get used to from our every-day operating systems and browsers (in this case selecting all text with Control+A).

And while you're at it, how about adding a reset button to any GUI control that reverts it back to a self-defined default value or marking a text or number field as required, which you can read more about in the linked blog posts.

Anyway, I hope you found this solution to a somewhat niche requirement helpful, even though it's not as sexy as dropping a few lines of code in your editor script, but I don't think there's a simpler approach to this behavior than this.

Fri May 08 2020

Comments