@ -3999,6 +3999,21 @@ static void InputTextReconcileUndoStateAfterUserCallback(ImGuiInputTextState* st
p [ i ] = ImStb : : STB_TEXTEDIT_GETCHAR ( state , first_diff + i ) ;
}
// As InputText() retain textual data and we currently provide a path for user to not retain it (via local variables)
// we need some form of hook to reapply data back to user buffer on deactivation frame. (#4714)
// It would be more desirable that we discourage users from taking advantage of the "user not retaining data" trick,
// but that more likely be attractive when we do have _NoLiveEdit flag available.
void ImGui : : InputTextDeactivateHook ( ImGuiID id )
{
ImGuiContext & g = * GImGui ;
ImGuiInputTextState * state = & g . InputTextState ;
if ( id = = 0 | | state - > ID ! = id )
return ;
g . InputTextDeactivatedState . ID = state - > ID ;
g . InputTextDeactivatedState . TextA . resize ( state - > CurLenA + 1 ) ;
memcpy ( g . InputTextDeactivatedState . TextA . Data , state - > TextA . Data , state - > CurLenA + 1 ) ;
}
// Edit a string of text
// - buf_size account for the zero-terminator, so a buf_size of 6 can hold "Hello" but not "Hello!".
// This is so we can easily call InputText() on static arrays using ARRAYSIZE() and to match
@ -4113,6 +4128,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
state = & g . InputTextState ;
state - > CursorAnimReset ( ) ;
// Backup state of deactivating item so they'll have a chance to do a write to output buffer on the same frame they report IsItemDeactivatedAfterEdit (#4714)
InputTextDeactivateHook ( state - > ID ) ;
// Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)
// From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode)
const int buf_len = ( int ) strlen ( buf ) ;
@ -4525,6 +4543,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Push records into the undo stack so we can CTRL+Z the revert operation itself
apply_new_text = state - > InitialTextA . Data ;
apply_new_text_length = state - > InitialTextA . Size - 1 ;
value_changed = true ;
ImVector < ImWchar > w_text ;
if ( apply_new_text_length > 0 )
{
@ -4638,10 +4657,24 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
{
apply_new_text = state - > TextA . Data ;
apply_new_text_length = state - > CurLenA ;
value_changed = true ;
}
}
}
// Handle reapplying final data on deactivation (see InputTextDeactivateHook() for details)
if ( g . InputTextDeactivatedState . ID = = id )
{
if ( g . ActiveId ! = id & & IsItemDeactivatedAfterEdit ( ) & & ! is_readonly )
{
apply_new_text = g . InputTextDeactivatedState . TextA . Data ;
apply_new_text_length = g . InputTextDeactivatedState . TextA . Size - 1 ;
value_changed | = ( strcmp ( g . InputTextDeactivatedState . TextA . Data , buf ) ! = 0 ) ;
//IMGUI_DEBUG_LOG("InputText(): apply Deactivated data for 0x%08X: \"%.*s\".\n", id, apply_new_text_length, apply_new_text);
}
g . InputTextDeactivatedState . ID = 0 ;
}
// Copy result to user buffer. This can currently only happen when (g.ActiveId == id)
if ( apply_new_text ! = NULL )
{
@ -4669,7 +4702,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// If the underlying buffer resize was denied or not carried to the next frame, apply_new_text_length+1 may be >= buf_size.
ImStrncpy ( buf , apply_new_text , ImMin ( apply_new_text_length + 1 , buf_size ) ) ;
value_changed = true ;
}
// Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value)