diff --git a/imgui.cpp b/imgui.cpp index 7e82a5ed8..2fbc33f6c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5686,6 +5686,8 @@ void ImGui::NewFrame() if (g.DeactivatedItemData.ElapseFrame < g.FrameCount) g.DeactivatedItemData.ID = 0; g.DeactivatedItemData.IsAlive = false; + if (g.InputTextDeactivatedState.ElapseFrame < g.FrameCount) + g.InputTextDeactivatedState.ID = 0; // Record when we have been stationary as this state is preserved while over same item. // FIXME: The way this is expressed means user cannot alter HoverStationaryDelay during the frame to use varying values. diff --git a/imgui_internal.h b/imgui_internal.h index 23b8ec0fd..b92274846 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1239,10 +1239,11 @@ struct IMGUI_API ImGuiMenuColumns struct IMGUI_API ImGuiInputTextDeactivatedState { ImGuiID ID; // widget id owning the text state (which just got deactivated) + int ElapseFrame; ImVector TextA; // text buffer ImGuiInputTextDeactivatedState() { memset((void*)this, 0, sizeof(*this)); } - void ClearFreeMemory() { ID = 0; TextA.clear(); } + void ClearFreeMemory() { ID = 0; ElapseFrame = 0; TextA.clear(); } }; // Forward declare imstb_textedit.h structure + make its main configuration define accessible diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 11b7da0b8..f1517273a 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4586,8 +4586,11 @@ void ImGui::InputTextDeactivateHook(ImGuiID id) ImGuiInputTextState* state = &g.InputTextState; if (id == 0 || state->ID != id) return; + if (!state->EditedBefore) + return; //IMGUI_DEBUG_LOG_ACTIVEID("InputTextDeactivateHook() id = 0x%08X\n", id); g.InputTextDeactivatedState.ID = state->ID; + g.InputTextDeactivatedState.ElapseFrame = g.FrameCount + 1; if (state->Flags & ImGuiInputTextFlags_ReadOnly) { g.InputTextDeactivatedState.TextA.resize(0); // In theory this data won't be used, but clear to be neat. @@ -5380,6 +5383,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ IM_ASSERT(callback_data.BufTextLen == (int)ImStrlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text! InputTextReconcileUndoState(state, state->CallbackTextBackup.Data, state->CallbackTextBackup.Size - 1, callback_data.Buf, callback_data.BufTextLen); state->TextLen = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen() + state->EditedBefore = state->EditedThisFrame = true; state->CursorAnimReset(); } } @@ -5399,7 +5403,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // This is used when e.g. losing focus or tabbing out into another InputText() which may already be using the temp buffer. if (g.InputTextDeactivatedState.ID == id) { - if (g.ActiveId != id && IsItemDeactivatedAfterEdit() && !is_readonly && strcmp(g.InputTextDeactivatedState.TextA.Data, buf) != 0) + // The state only exists after an Edit. More-over we cannot use IsItemDeactivatedAfterEdit(). + if (g.ActiveId != id && IsItemDeactivated() && !is_readonly && strcmp(g.InputTextDeactivatedState.TextA.Data, buf) != 0) { apply_new_text = g.InputTextDeactivatedState.TextA.Data; apply_new_text_length = g.InputTextDeactivatedState.TextA.Size - 1; @@ -5445,7 +5450,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value) // Otherwise request text input ahead for next frame. if (g.ActiveId == id && clear_active_id) + { + state->ID = 0; // To avoid InputTextDeactivateHook() unnecessarily running, which wouldn't be harmful but wasteful. ClearActiveID(); + state->ID = id; + } // Render frame if (!is_multiline)