From f4ed421a88db61ebaf874506c13d1cf1a8a8281f Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 9 Apr 2026 14:52:49 +0200 Subject: [PATCH] InputText: CharFilter callback event sets CursorPos/SelectionStart/SelectionEnd. (#816) --- docs/CHANGELOG.txt | 1 + docs/TODO.txt | 1 - imgui.h | 8 ++++---- imgui_widgets.cpp | 3 +++ 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index fbd663bad..c6f9baa5d 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -47,6 +47,7 @@ Other Changes: - InputTextMultiline: fixed an issue processing deactivation logic when an active multi-line edit is clipped due to being out of view. - Fixed a crash when toggling ReadOnly while active. (#9354) + - CharFilter callback event sets CursorPos/SelectionStart/SelectionEnd. (#816) - Tables: - Fixed issues reporting ideal size to parent window/container: (#9352, #7651) - When both scrollbars are visible but only one of ScrollX/ScrollY was explicitly requested. diff --git a/docs/TODO.txt b/docs/TODO.txt index 6107e5dc0..30df62e32 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -63,7 +63,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - input text: preserve scrolling when unfocused? - input text: reorganize event handling, allow CharFilter to modify buffers, allow multiple events? (#541) - - input text: expose CursorPos in char filter event (#816) - input text: try usage idiom of using InputText with data only exposed through get/set accessors, without extraneous copy/alloc. (#3009) - input text: access public fields via a non-callback API e.g. InputTextGetState("xxx") that may return nullptr if not active (available in internals) - input text: flag to disable live update of the user buffer (also applies to float/int text input) (#701) diff --git a/imgui.h b/imgui.h index 75277db87..e73b5b0d3 100644 --- a/imgui.h +++ b/imgui.h @@ -2642,7 +2642,7 @@ struct ImGuiInputTextCallbackData ImGuiInputTextFlags EventFlag; // One ImGuiInputTextFlags_Callback* // Read-only ImGuiInputTextFlags Flags; // What user passed to InputText() // Read-only void* UserData; // What user passed to InputText() // Read-only - ImGuiID ID; // Widget ID // Read-only + ImGuiID ID; // Widget ID // Read-only // Arguments for the different callback events // - During Resize callback, Buf will be same as your input buffer. @@ -2656,9 +2656,9 @@ struct ImGuiInputTextCallbackData char* Buf; // Text buffer // Read-write // [Resize] Can replace pointer / [Completion,History,Always] Only write to pointed data, don't replace the actual pointer! int BufTextLen; // Text length (in bytes) // Read-write // [Resize,Completion,History,Always] Exclude zero-terminator storage. In C land: == strlen(some_text), in C++ land: string.length() int BufSize; // Buffer size (in bytes) = capacity+1 // Read-only // [Resize,Completion,History,Always] Include zero-terminator storage. In C land: == ARRAYSIZE(my_char_array), in C++ land: string.capacity()+1 - int CursorPos; // // Read-write // [Completion,History,Always] - int SelectionStart; // // Read-write // [Completion,History,Always] == to SelectionEnd when no selection - int SelectionEnd; // // Read-write // [Completion,History,Always] + int CursorPos; // // Read-write // [Completion,History,Always,CharFilter] + int SelectionStart; // // Read-write // [Completion,History,Always,CharFilter] == to SelectionEnd when no selection + int SelectionEnd; // // Read-write // [Completion,History,Always,CharFilter] // Helper functions for text manipulation. // Use those function to benefit from the CallbackResize behaviors. Calling those function reset the selection. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 162605148..3483acb6c 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4521,6 +4521,9 @@ static bool InputTextFilterCharacter(ImGuiContext* ctx, ImGuiInputTextState* sta callback_data.EventFlag = ImGuiInputTextFlags_CallbackCharFilter; callback_data.EventChar = (ImWchar)c; callback_data.EventActivated = (g.ActiveId == state->ID && g.ActiveIdIsJustActivated); + callback_data.CursorPos = state->Stb->cursor; + callback_data.SelectionStart = state->Stb->select_start; + callback_data.SelectionEnd = state->Stb->select_end; callback_data.UserData = user_data; if (callback(&callback_data) != 0) return false;