How to Use InputText Callbacks for Custom Text Processing in Dear ImGui

Dear ImGui's InputText widgets expose a flexible callback mechanism via ImGuiInputTextFlags_Callback* flags that allows you to intercept every edit, filter characters, and manipulate buffers through the ImGuiInputTextCallbackData structure.

Dear ImGui (ocornut/imgui) provides a powerful callback system for its input widgets that enables real-time text validation, dynamic buffer resizing, and custom completion behaviors. By leveraging the ImGuiInputTextCallbackData structure and specific callback flags defined in imgui.h, you can implement complex text processing logic directly within your GUI code. This article demonstrates how to configure and implement these callbacks using actual source patterns from the repository.

Understanding the Callback Architecture

The callback system centers on three core components defined in [imgui.h](https://github.com/ocornut/imgui/blob/master/imgui.h).

ImGuiInputTextCallbackData (lines 2670-2700) is the primary structure passed to your callback function. It contains the current buffer (Buf), buffer size (BufSize), text length (BufTextLen), cursor position (CursorPos), selection range, and the event that triggered the callback (EventFlag). The structure also provides helper methods InsertChars() and DeleteChars() to safely modify text while keeping internal state consistent.

Callback Flags (lines 1299-1304) enable specific interception points:

  • ImGuiInputTextFlags_CallbackEdit – Called after any edit operation.
  • ImGuiInputTextFlags_CallbackAlways – Called every frame while the widget is active.
  • ImGuiInputTextFlags_CallbackCompletion – Triggered on TAB for auto-completion.
  • ImGuiInputTextFlags_CallbackHistory – Triggered on Up/Down arrows for history navigation.
  • ImGuiInputTextFlags_CallbackCharFilter – Called for each input character to allow filtering.
  • ImGuiInputTextFlags_CallbackResize – Request to grow the backing buffer.

InputTextEx in [imgui_widgets.cpp](https://github.com/ocornut/imgui/blob/master/imgui_widgets.cpp) (lines 4010-4022) implements the core dispatch logic, checking enabled flags and invoking your callback with the appropriate event data.

Configuring InputText Callbacks

To enable custom processing, pass the desired flags and a callback function to any InputText* variant:

// Function signature requirement
typedef int (*ImGuiInputTextCallback)(ImGuiInputTextCallbackData* data);

// Usage with InputText
ImGui::InputText("Label", buffer, buffer_size, 
                 ImGuiInputTextFlags_CallbackCharFilter | 
                 ImGuiInputTextFlags_CallbackResize,
                 MyCallbackFunction, user_data_pointer);

The callback must match the signature int (*)(ImGuiInputTextCallbackData*) and return 0 on success. For CallbackCharFilter, returning 1 discards the character.

Processing Callback Events

Inside your callback, inspect data->EventFlag to determine why you were invoked:

  1. Read the event type via data->EventFlag (e.g., ImGuiInputTextFlags_CallbackCharFilter).
  2. Modify text using data->InsertChars(pos, text) or data->DeleteChars(pos, size) for safe manipulation.
  3. Direct buffer access is available via data->Buf, but you must set data->BufDirty = true if you modify it manually.
  4. Access custom state through data->UserData, which receives the pointer passed to InputText.

Practical Implementation Examples

Filtering Input to Allow Only Digits

Use ImGuiInputTextFlags_CallbackCharFilter to validate individual characters before they enter the buffer:

int DigitsOnlyCallback(ImGuiInputTextCallbackData* data)
{
    if (data->EventFlag == ImGuiInputTextFlags_CallbackCharFilter)
    {
        if (data->EventChar < '0' || data->EventChar > '9')
            return 1;  // Discard non-digit characters
    }
    return 0;
}

// Usage
char buf[64] = "";
ImGui::InputText("Digits only", buf, IM_ARRAYSIZE(buf),
                 ImGuiInputTextFlags_CallbackCharFilter,
                 DigitsOnlyCallback);

Dynamic Buffer Resizing with std::string

The [imgui_stdlib.cpp](https://github.com/ocornut/imgui/blob/master/misc/cpp/imgui_stdlib.cpp) implementation (lines 42-65) demonstrates the standard pattern for growing a std::string:

int ResizeCallback(ImGuiInputTextCallbackData* data)
{
    if (data->EventFlag == ImGuiInputTextFlags_CallbackResize)
    {
        std::string* str = static_cast<std::string*>(data->UserData);
        str->resize(data->BufSize);  // Resize to requested capacity
        data->Buf = const_cast<char*>(str->c_str());
    }
    return 0;
}

// Usage
static std::string text;
ImGui::InputText("Dynamic", &text[0], text.capacity() + 1,
                 ImGuiInputTextFlags_CallbackResize,
                 ResizeCallback, (void*)&text);

Implementing Tab Auto-Completion

Handle ImGuiInputTextFlags_CallbackCompletion to insert suggested text:

int CompletionCallback(ImGuiInputTextCallbackData* data)
{
    if (data->EventFlag == ImGuiInputTextFlags_CallbackCompletion)
    {
        const char* candidates[] = { "apple", "apricot", "banana" };
        std::string current(data->Buf, data->BufTextLen);
        
        for (const char* cand : candidates)
        {
            if (strncmp(cand, current.c_str(), current.size()) == 0)
            {
                data->DeleteChars(0, data->BufTextLen);
                data->InsertChars(0, cand);
                break;
            }
        }
    }
    return 0;
}

Key Source Files to Reference

Summary

  • Enable callbacks by OR-ing ImGuiInputTextFlags_Callback* flags when calling InputText, InputTextMultiline, or InputTextWithHint.
  • Implement the callback signature int (*)(ImGuiInputTextCallbackData*) and inspect data->EventFlag to handle specific events.
  • Modify text safely using InsertChars() and DeleteChars(), or set BufDirty = true after direct buffer manipulation.
  • Manage state through the UserData pointer to access application-specific structures like std::string or history buffers.
  • Return values affect behavior: return 0 to accept changes, 1 to reject characters in filter mode.

Frequently Asked Questions

How do I filter specific characters in an InputText field?

Enable ImGuiInputTextFlags_CallbackCharFilter and inspect data->EventChar in your callback. Return 1 to discard the character, or modify data->EventChar to substitute a different character before insertion.

Can I resize the text buffer while the user is typing?

Yes, enable ImGuiInputTextFlags_CallbackResize. When triggered, allocate a new buffer large enough for the requested size, copy existing content, and update data->Buf and data->BufSize accordingly. The imgui_stdlib.cpp reference shows exactly how to handle this for std::string objects.

What is the difference between CallbackEdit and CallbackAlways?

CallbackEdit fires only when the text content actually changes, making it ideal for validation or auto-save features. CallbackAlways executes every frame while the widget remains active, which is useful for continuous processing or live preview updates regardless of whether the text changed.

How do I implement command history with Up/Down arrows?

Enable ImGuiInputTextFlags_CallbackHistory. In your callback, check data->EventFlag for ImGuiInputTextFlags_CallbackHistory, then replace the buffer content with entries from your application's history stack stored in data->UserData. Set data->CursorPos to the end of the inserted text for proper navigation.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →