From 2cffcbdc64ee9301e473225fff697049697aac2d Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 17 Sep 2021 15:44:43 +0200 Subject: [PATCH] InputText: fix Space key with nav enabled interfering with input text boxes (fix bd6c9e99). made it possible to activate InputText with tweak gamepad button (why not, now that we can cancel) (#4552, #2321) --- docs/CHANGELOG.txt | 3 +-- imgui.cpp | 2 +- imgui.h | 2 +- imgui_widgets.cpp | 13 ++++++++++--- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 09e395da..557b7154 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -45,8 +45,7 @@ Other Changes: - Windows: Fixed background order of overlapping childs submitted sequentially. (#4493) - InputTextMultiline: Fixed label size not being included into window contents rect unless the whole widget is clipped. -- InputText: Allow cancelling/validating input with gamepad nav events to facilitate undoing - an accidental press on NavInput (Triangle button on PS4/PS5) without a wired keyboard. (#2321) +- InputText: Allow activating/cancelling/validating input with gamepad nav events. (#2321, #4552) - TextUnformatted: Accept null ranges including (NULL,NULL) without asserting, in order to conform to common idioms (e.g. passing .data(), .data() + .size() from a null string). (#3615) - Disabled: Added assert guard for mismatching BeginDisabled()/EndDisabled() blocks. (#211) diff --git a/imgui.cpp b/imgui.cpp index 0a72737a..4f3105f2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5118,7 +5118,7 @@ void ImGui::EndChild() ItemAdd(bb, window->ChildId); RenderNavHighlight(bb, window->ChildId); - // When browsing a window that has no activable items (scroll only) we keep a highlight on the child + // When browsing a window that has no activable items (scroll only) we keep a highlight on the child (pass g.NavId to trick into always displaying) if (window->DC.NavLayersActiveMask == 0 && window == g.NavWindow) RenderNavHighlight(ImRect(bb.Min - ImVec2(2, 2), bb.Max + ImVec2(2, 2)), g.NavId, ImGuiNavHighlightFlags_TypeThin); } diff --git a/imgui.h b/imgui.h index 3f107e49..a1d1f4b0 100644 --- a/imgui.h +++ b/imgui.h @@ -64,7 +64,7 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) #define IMGUI_VERSION "1.85 WIP" -#define IMGUI_VERSION_NUM 18415 +#define IMGUI_VERSION_NUM 18416 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_HAS_TABLE diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 3aef1a49..590cb4bf 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -3990,6 +3990,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ window->DC.CursorPos = backup_pos; // We reproduce the contents of BeginChildFrame() in order to provide 'label' so our window internal data are easier to read/debug. + // FIXME-NAV: Pressing NavActivate will trigger general child activation right before triggering our own below. Harmless but bizarre. PushStyleColor(ImGuiCol_ChildBg, style.Colors[ImGuiCol_FrameBg]); PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding); PushStyleVar(ImGuiStyleVar_ChildBorderSize, style.FrameBorderSize); @@ -4027,7 +4028,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ const bool focus_requested_by_tabbing = (item_status_flags & ImGuiItemStatusFlags_FocusedByTabbing) != 0; const bool user_clicked = hovered && io.MouseClicked[0]; - const bool user_nav_input_start = (g.ActiveId != id) && ((g.NavActivateInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_Keyboard)); + const bool user_nav_input_start = (g.ActiveId != id) && (g.NavActivateInputId == id || g.NavActivateId == id); const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == GetWindowScrollbarID(draw_window, ImGuiAxis_Y); const bool user_scroll_active = is_multiline && state != NULL && g.ActiveId == GetWindowScrollbarID(draw_window, ImGuiAxis_Y); @@ -4255,7 +4256,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ const bool is_redo = ((is_shortcut_key && IsKeyPressedMap(ImGuiKey_Y)) || (is_osx_shift_shortcut && IsKeyPressedMap(ImGuiKey_Z))) && !is_readonly && is_undoable; // We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful. - const bool is_validate = IsKeyPressedMap(ImGuiKey_Enter) || IsKeyPressedMap(ImGuiKey_KeyPadEnter) || IsNavInputTest(ImGuiNavInput_Activate, ImGuiInputReadMode_Pressed) || IsNavInputTest(ImGuiNavInput_Input, ImGuiInputReadMode_Pressed); + const bool is_validate_enter = IsKeyPressedMap(ImGuiKey_Enter) || IsKeyPressedMap(ImGuiKey_KeyPadEnter); + const bool is_validate_nav = (g.NavInputSource == ImGuiInputSource_Gamepad && IsNavInputTest(ImGuiNavInput_Activate, ImGuiInputReadMode_Pressed)) || IsNavInputTest(ImGuiNavInput_Input, ImGuiInputReadMode_Pressed); const bool is_cancel = IsKeyPressedMap(ImGuiKey_Escape) || IsNavInputTest(ImGuiNavInput_Cancel, ImGuiInputReadMode_Pressed); if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); } @@ -4278,7 +4280,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ } state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask); } - else if (is_validate) + else if (is_validate_enter) { bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0; if (!is_multiline || (ctrl_enter_for_new_line && !io.KeyCtrl) || (!ctrl_enter_for_new_line && io.KeyCtrl)) @@ -4292,6 +4294,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ state->OnKeyPressed((int)c); } } + else if (is_validate_nav) + { + IM_ASSERT(!is_validate_enter); + enter_pressed = clear_active_id = true; + } else if (is_cancel) { clear_active_id = cancel_edit = true;