# How to Implement Custom InputText Behavior with ImGuiInputTextCallback in Dear ImGui

> Learn to implement custom InputText behavior in Dear ImGui using ImGuiInputTextCallback. Handle events like resize and filtering by manipulating ImGuiInputTextCallbackData within your callback function.

- Repository: [omar/imgui](https://github.com/ocornut/imgui)
- Tags: how-to-guide
- Published: 2026-07-18

---

**To implement custom InputText behavior in Dear ImGui, pass one or more `ImGuiInputTextFlags_Callback*` flags to `InputText()` or `InputTextMultiline()`, then handle events like resize, character filtering, or completion inside a callback function that manipulates the `ImGuiInputTextCallbackData` structure.**

The `ocornut/imgui` library provides a powerful callback system that lets you intercept and modify text input at multiple stages of the editing pipeline. By understanding the `ImGuiInputTextCallbackData` structure and the specific flags available, you can implement dynamic resizing, input validation, auto-completion, and history navigation.

## Understanding the ImGuiInputTextCallback System

Dear ImGui's `InputText()` family functions are thin wrappers around the internal `InputTextEx()` implementation located in **[`imgui_widgets.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_widgets.cpp)**. When you pass callback flags, the widget constructs an `ImGuiInputTextCallbackData` object and invokes your user-supplied function whenever the corresponding event occurs.

The following flags control when your callback executes:

- **`ImGuiInputTextFlags_CallbackResize`** – Triggered when the buffer needs to grow beyond the initially provided `buf_size`. Use this to reallocate backing storage and update `data->Buf` and `data->BufSize`.
- **`ImGuiInputTextFlags_CallbackEdit`** – Called after any edit operation (insertion, deletion). Inspect or modify `data->Buf`, `CursorPos`, and `SelectionStart/End`.
- **`ImGuiInputTextFlags_CallbackAlways`** – Executed every frame while the widget has focus. Ideal for live validation and visual feedback.
- **`ImGuiInputTextFlags_CallbackCharFilter`** – Invoked for each typed character before insertion. Replace `data->EventChar` or discard it by returning `1`.
- **`ImGuiInputTextFlags_CallbackCompletion`** – Fired when the user presses **TAB**. Implement suggestion logic or insert completion characters here.
- **`ImGuiInputTextFlags_CallbackHistory`** – Triggered on **↑/↓** key presses. Use this to navigate a custom command history.

The callback data structure is defined in **[`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h)** (around line 2670) and provides helper methods like `InsertChars()` and `DeleteChars()` that automatically respect the resize callback.

## Implementing the Core Callback Handler

To create a robust implementation, follow this workflow:

1. **Create a user-data struct** to hold your dynamic buffer (e.g., `std::string`) and any additional state or chained callbacks.
2. **Set the appropriate flags** when calling `InputText()` or `InputTextMultiline()`.
3. **Switch on `data->EventFlag`** inside your callback to handle specific events:
   - For `CallbackResize`, reallocate your buffer, update `data->Buf` with the new pointer, and set `data->BufSize`.
   - For `CallbackCharFilter`, inspect `data->EventChar` and return `1` to discard unwanted characters.
   - For edit or always callbacks, modify `data->Buf` directly and set `data->BufDirty = true` to signal changes.
4. **Return 0** to accept the event (except for character filtering where returning `1` discards the character).

The widget maintains its internal state in `ImGuiInputTextState` (a member of `ImGuiContext`), and the callback is invoked from `InputTextEx()` after the state processes the event. Prefer using `InsertChars()` and `DeleteChars()` over manual buffer manipulation, as these methods handle reallocation boundaries safely.

## Complete Example: Dynamic std::string with Character Filtering

Below is a production-ready pattern that combines dynamic resizing with input validation. This example uses a `std::string` as backing storage and rejects numeric digits.

```cpp
// User-data structure holding the string and optional chained callback
struct InputTextUserData {
    std::string* Str;
    ImGuiInputTextCallback UserCallback = nullptr;
    void* UserCallbackData = nullptr;
};

// The callback implementation
int CustomInputCallback(ImGuiInputTextCallbackData* data)
{
    InputTextUserData* user = (InputTextUserData*)data->UserData;

    // Handle buffer resize for dynamic std::string
    if (data->EventFlag == ImGuiInputTextFlags_CallbackResize)
    {
        std::string& s = *user->Str;
        IM_ASSERT(data->Buf == s.c_str());  // Sanity check
        s.resize(data->BufTextLen);
        data->Buf = (char*)s.c_str();
        data->BufSize = s.capacity() + 1;
        return 0;
    }

    // Filter out digits (0-9)
    if (data->EventFlag == ImGuiInputTextFlags_CallbackCharFilter)
    {
        if (data->EventChar >= '0' && data->EventChar <= '9')
            return 1;  // Discard digit
    }

    // Support callback chaining
    if (user->UserCallback)
    {
        data->UserData = user->UserCallbackData;
        return user->UserCallback(data);
    }

    return 0;
}

// Usage in your GUI code
void ShowCustomInput()
{
    static std::string text;
    InputTextUserData cb_data = { &text, nullptr, nullptr };
    
    ImGuiInputTextFlags flags = ImGuiInputTextFlags_CallbackResize |
                                ImGuiInputTextFlags_CallbackCharFilter;
    
    ImGui::InputText("Name (letters only)", &text, flags, 
                     CustomInputCallback, &cb_data);
}

```

**Key implementation details:**

- The **resize callback** ensures the `std::string` grows automatically as the user types.
- The **character filter** intercepts digits before they reach the buffer.
- The callback uses `data->BufTextLen` to determine the required size, not `strlen()`.

## Common Callback Patterns

Use these patterns to solve specific interaction requirements:

**Auto-Completion (TAB)**
Enable `ImGuiInputTextFlags_CallbackCompletion` and check for `data->EventKey == ImGuiKey_Tab`. Use `data->InsertChars()` to append suggestions at `data->CursorPos`.

**History Navigation (↑/↓)**
With `ImGuiInputTextFlags_CallbackHistory`, detect `data->EventKey` for Up/Down arrows. Maintain a `std::vector<std::string>` history and replace `data->Buf` content using `DeleteChars()` followed by `InsertChars()`.

**Live Validation**
Combine `ImGuiInputTextFlags_CallbackEdit` or `CallbackAlways` with regex or custom logic. If validation fails, modify `data->Buf` to correct the input and set `data->BufDirty = true`.

**Simple Resize Wrapper**
For cases requiring only dynamic resizing without other logic, reference the implementation in **[`misc/cpp/imgui_stdlib.cpp`](https://github.com/ocornut/imgui/blob/main/misc/cpp/imgui_stdlib.cpp)**, which demonstrates the minimal resize callback pattern for `std::string` integration.

## Summary

- **`InputText()`** and **`InputTextMultiline()`** forward to `InputTextEx()` in [`imgui_widgets.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_widgets.cpp), which manages the callback dispatch loop.
- Use **`ImGuiInputTextFlags_CallbackResize`** to support dynamic buffers like `std::string` by updating `data->Buf` and `data->BufSize` during reallocation.
- Implement **`ImGuiInputTextFlags_CallbackCharFilter`** to sanitize input character-by-character before insertion.
- Prefer **`InsertChars()`** and **`DeleteChars()`** over raw buffer manipulation to ensure automatic resize handling.
- Chain callbacks by storing the original callback pointer in your user-data struct and invoking it after your custom logic.

## Frequently Asked Questions

### What is the difference between CallbackEdit and CallbackAlways?

**`ImGuiInputTextFlags_CallbackEdit`** fires only when the buffer content actually changes (insertions, deletions, or replacements), making it efficient for validation logic that must run after modifications. **`ImGuiInputTextFlags_CallbackAlways`** executes every frame while the widget retains focus, which is useful for continuous visual feedback or handling special keys like Enter for auto-indentation, even when no text changes occur.

### How do I properly resize a std::string inside the callback?

When handling `ImGuiInputTextFlags_CallbackResize`, resize your `std::string` to `data->BufTextLen`, then update `data->Buf` with `(char*)s.c_str()` and `data->BufSize` with the new capacity plus one. Always verify that `data->Buf` matches your string's internal pointer before resizing to ensure memory consistency.

### Can I chain multiple callbacks together?

Yes. Store the additional callback function pointer and its user data inside your own user-data structure. After processing your custom logic, forward the call by setting `data->UserData` to the stored user data and returning the result of the chained callback function.

### Why is my buffer pointer invalid after resizing?

If you trigger a buffer modification (like `InsertChars()`) without the `ImGuiInputTextFlags_CallbackResize` flag set, or if you manually write to `data->Buf` without updating the pointer after a resize, the internal state may reference freed memory. Always ensure the resize flag is set when using dynamic buffers, and update `data->Buf` immediately after any reallocation.