From 6cfe3ddf528a13728a75df7db4c856d5d8770e2e Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 14 Dec 2023 17:02:23 +0100 Subject: [PATCH] InputTextMultiline: Tabbing through a multi-line text editor using ImGuiInputTextFlags_AllowTabInput doesn't activate it. (#3092, #5759, #787) --- docs/CHANGELOG.txt | 3 +++ imgui.cpp | 2 +- imgui_demo.cpp | 1 + imgui_internal.h | 1 + imgui_widgets.cpp | 6 +++++- 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 44f9fc4ef7fa..f4543da00b94 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -65,6 +65,9 @@ Other changes: (namely Selectables and Treenodes using SpanAllColumn flag) so the highlight properly covers all columns. (#7049, #4281, #3272) - InputTextMultiline: Fixed Tab character input not repeating (1.89.4 regression). +- InputTextMultiline: Tabbing through a multi-line text editor which allows Tab character inputs + (using the ImGuiInputTextFlags_AllowTabInput flag) doesn't automatically activate it, in order + to allow passing through multiple widgets easily. (#3092, #5759, #787) - DragScalarN, SliderScalarN, InputScalarN, PushMultiItemsWidths: improve multi-components width computation to better distribute the error. (#7120, #7121) [@Nahor] - Menus: Tweaked hover slack logic, adding a timer to avoid situations where a slow vertical diff --git a/imgui.cpp b/imgui.cpp index 7d6627579ccd..a7a9cf98a2bb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12034,7 +12034,7 @@ void ImGui::NavMoveRequestApplyResult() g.NavNextActivateId = result->ID; g.NavNextActivateFlags = ImGuiActivateFlags_None; if (g.NavMoveFlags & ImGuiNavMoveFlags_IsTabbing) - g.NavNextActivateFlags |= ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_TryToPreserveState; + g.NavNextActivateFlags |= ImGuiActivateFlags_PreferInput | ImGuiActivateFlags_TryToPreserveState | ImGuiActivateFlags_FromTabbing; } // Enable nav highlight diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 86d5ad367aa1..763e0a9e9622 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1479,6 +1479,7 @@ static void ShowDemoWindowWidgets() HelpMarker("You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputTextMultiline() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example. (This is not demonstrated in imgui_demo.cpp because we don't want to include in here)"); ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly); ImGui::CheckboxFlags("ImGuiInputTextFlags_AllowTabInput", &flags, ImGuiInputTextFlags_AllowTabInput); + ImGui::SameLine(); HelpMarker("When _AllowTabInput is set, passing through the widget with Tabbing doesn't automatically activate it, in order to also cycling through subsequent widgets."); ImGui::CheckboxFlags("ImGuiInputTextFlags_CtrlEnterForNewLine", &flags, ImGuiInputTextFlags_CtrlEnterForNewLine); ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), flags); ImGui::TreePop(); diff --git a/imgui_internal.h b/imgui_internal.h index ee8098f75154..35c48616e91a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1488,6 +1488,7 @@ enum ImGuiActivateFlags_ ImGuiActivateFlags_PreferInput = 1 << 0, // Favor activation that requires keyboard text input (e.g. for Slider/Drag). Default for Enter key. ImGuiActivateFlags_PreferTweak = 1 << 1, // Favor activation for tweaking with arrows or gamepad (e.g. for Slider/Drag). Default for Space key and if keyboard is not used. ImGuiActivateFlags_TryToPreserveState = 1 << 2, // Request widget to preserve state if it can (e.g. InputText will try to preserve cursor/selection) + ImGuiActivateFlags_FromTabbing = 1 << 3, // Activation requested by a tabbing request }; // Early work-in-progress API for ScrollToItem() diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 7194ad3eb1e2..5ad751d4609a 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4126,7 +4126,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ item_data_backup = g.LastItemData; window->DC.CursorPos = backup_pos; - // Prevent NavActivate reactivating in BeginChild(). + // Prevent NavActivation from Tabbing when our widget accepts Tab inputs: this allows cycling through widgets without stopping. + if (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_FromTabbing) && (flags & ImGuiInputTextFlags_AllowTabInput)) + g.NavActivateId = 0; + + // Prevent NavActivate reactivating in BeginChild() when we are already active. const ImGuiID backup_activate_id = g.NavActivateId; if (g.ActiveId == id) // Prevent reactivation g.NavActivateId = 0;