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:
- Read the event type via
data->EventFlag(e.g.,ImGuiInputTextFlags_CallbackCharFilter). - Modify text using
data->InsertChars(pos, text)ordata->DeleteChars(pos, size)for safe manipulation. - Direct buffer access is available via
data->Buf, but you must setdata->BufDirty = trueif you modify it manually. - Access custom state through
data->UserData, which receives the pointer passed toInputText.
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
- [
imgui.h](https://github.com/ocornut/imgui/blob/master/imgui.h): ContainsImGuiInputTextCallbackDatadefinition and all callback flags. - [
imgui_widgets.cpp](https://github.com/ocornut/imgui/blob/master/imgui_widgets.cpp): HousesInputTextExand the callback dispatch logic. - [
misc/cpp/imgui_stdlib.cpp](https://github.com/ocornut/imgui/blob/master/misc/cpp/imgui_stdlib.cpp): Reference implementation forstd::stringresize callbacks. - [
imgui_demo.cpp](https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp): Contains working examples of various callback patterns.
Summary
- Enable callbacks by OR-ing
ImGuiInputTextFlags_Callback*flags when callingInputText,InputTextMultiline, orInputTextWithHint. - Implement the callback signature
int (*)(ImGuiInputTextCallbackData*)and inspectdata->EventFlagto handle specific events. - Modify text safely using
InsertChars()andDeleteChars(), or setBufDirty = trueafter direct buffer manipulation. - Manage state through the
UserDatapointer to access application-specific structures likestd::stringor history buffers. - Return values affect behavior: return
0to accept changes,1to 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →