How to Use InputText with Callbacks for Custom Text Processing in ImGui
ImGui::InputText() accepts an ImGuiInputTextCallback function pointer that lets you intercept editing events to resize buffers dynamically, filter characters, implement autocomplete, or monitor cursor changes.
The ocornut/imgui library exposes a sophisticated callback system for text input widgets. By combining callback flags with the ImGuiInputTextCallbackData structure, you can hook into the edit lifecycle of InputText, InputTextMultiline, and InputTextWithHint to perform custom validation, memory management, or command-line-style features.
Callback Types and Flags
InputText() supports several distinct callback events triggered by specific flags. You can combine these flags to register multiple callbacks within a single function, checking data->EventFlag to distinguish the event type.
ImGuiInputTextFlags_CallbackResize – Triggered when the internal buffer needs to grow. Essential when using resizable containers like std::string instead of fixed-size char arrays. The callback must reallocate memory and update data->Buf and data->BufSize.
ImGuiInputTextFlags_CallbackCharFilter – Called for each character input before it is inserted. Return 1 to discard the character, or modify data->EventChar to substitute a different character.
ImGuiInputTextFlags_CallbackCompletion and ImGuiInputTextFlags_CallbackHistory – Standard events for Tab-completion and Up/Down arrow history navigation, commonly used in console or command-palette interfaces.
ImGuiInputTextFlags_CallbackAlways and ImGuiInputTextFlags_CallbackEdit – Called every frame or on every edit, allowing you to inspect cursor position, selection ranges, or modify buffer content while the widget maintains focus.
The ImGuiInputTextCallbackData Structure
According to the declaration on line 194 of imgui.h, the callback receives a pointer to ImGuiInputTextCallbackData, which contains the following key members:
- EventFlag – Identifies which flag triggered the callback (e.g.,
ImGuiInputTextFlags_CallbackResize). - Buf / BufTextLen / BufSize – The current text buffer, its length, and total capacity. For resize callbacks, you must update these fields after reallocation.
- CursorPos / SelectionStart / SelectionEnd – Current cursor location and text selection bounds, useful for context-aware processing.
- UserData – The opaque pointer passed as the last argument to
InputText(), typically used to access your application-specific buffer or state.
The callback function signature, defined on line 286 of imgui.h, is:
int MyCallback(ImGuiInputTextCallbackData* data);
Example: Dynamic Buffer Resizing with std::string
When using std::string as your backing storage, you must handle the resize callback to avoid buffer overflows. The implementation in misc/cpp/imgui_stdlib.h (lines 30-34) demonstrates the standard pattern:
#include "imgui.h"
#include "misc/cpp/imgui_stdlib.h"
std::string text;
ImGui::InputText("Label", &text, ImGuiInputTextFlags_None);
For a manual implementation using a custom buffer structure:
struct MyBuffer {
char* data;
int capacity;
};
static int ResizeCallback(ImGuiInputTextCallbackData* data)
{
if (data->EventFlag == ImGuiInputTextFlags_CallbackResize)
{
MyBuffer* buf = (MyBuffer*)data->UserData;
buf->capacity = data->BufSize;
buf->data = (char*)realloc(buf->data, buf->capacity);
data->Buf = buf->data;
}
return 0;
}
// Usage
MyBuffer mybuf = { (char*)malloc(128), 128 };
ImGui::InputText("Dynamic", mybuf.data, mybuf.capacity,
ImGuiInputTextFlags_CallbackResize,
ResizeCallback, &mybuf);
Example: Character Filtering
To restrict input to digits only, use the CallbackCharFilter flag and return 1 to reject non-matching characters:
static int FilterDigitsCallback(ImGuiInputTextCallbackData* data)
{
if (data->EventFlag == ImGuiInputTextFlags_CallbackCharFilter)
{
if (!isdigit(data->EventChar))
return 1; // Discard non-digit
}
return 0;
}
char buf[64] = "";
ImGui::InputText("Only digits", buf, sizeof(buf),
ImGuiInputTextFlags_CallbackCharFilter,
FilterDigitsCallback, nullptr);
Example: Tab Completion
Implement command palette behavior by handling the completion callback:
static const char* commands[] = { "help", "quit", "reset", nullptr };
static int CompletionCallback(ImGuiInputTextCallbackData* data)
{
if (data->EventFlag == ImGuiInputTextFlags_CallbackCompletion)
{
for (int i = 0; commands[i]; ++i)
{
if (strncmp(commands[i], data->Buf, data->BufTextLen) == 0)
{
data->InsertChars(data->BufTextLen,
commands[i] + data->BufTextLen);
break;
}
}
}
return 0;
}
char cmd[64] = "";
ImGui::InputText("Cmd", cmd, sizeof(cmd),
ImGuiInputTextFlags_CallbackCompletion,
CompletionCallback, nullptr);
Internal Implementation Details
As implemented in ocornut/imgui, the InputText() function forwards to InputTextEx (see line 3796 of imgui.cpp), which manages the actual editing state and invokes your callback at the appropriate moments. The internal state is maintained in ImGuiInputTextState (declared on line 1260 of imgui_internal.h), allowing callbacks to access low-level details such as undo/redo history and word selection when using the CallbackAlways flag.
Summary
- InputText callbacks enable custom text processing through the
ImGuiInputTextCallbackfunction pointer defined inimgui.h. - Use ImGuiInputTextFlags_CallbackResize to support dynamic buffers like
std::string, updatingdata->Bufanddata->BufSizein your callback. - Use ImGuiInputTextFlags_CallbackCharFilter to validate or replace individual characters before insertion.
- The ImGuiInputTextCallbackData struct provides access to buffer state, cursor position, and selection ranges.
- Internal implementation routes through
InputTextExinimgui.cppand maintains state inImGuiInputTextState.
Frequently Asked Questions
How do I automatically resize a std::string with InputText?
Include misc/cpp/imgui_stdlib.h and pass the string pointer to ImGui::InputText(). This header implements a resize callback that calls std::string::resize() when the ImGuiInputTextFlags_CallbackResize event fires, ensuring the buffer grows as the user types.
Can I block specific characters from being entered?
Yes. Set the ImGuiInputTextFlags_CallbackCharFilter flag and provide a callback that checks data->EventChar. Return 1 from the callback to discard the character, or modify data->EventChar to substitute a different value.
How do I implement command history navigation?
Use the ImGuiInputTextFlags_CallbackHistory flag. When the user presses Up or Down arrow keys, your callback receives this event with data->EventFlag set accordingly. You can then replace the buffer content using data->InsertChars() or data->DeleteChars() to show previous commands.
What is the difference between CallbackAlways and CallbackEdit?
CallbackAlways invokes your callback every frame while the widget is active, allowing continuous monitoring of cursor position or selection. CallbackEdit only fires when the buffer content actually changes, making it more efficient for validation that only needs to run on modifications.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →