From 7a56b411247a9bbe32b7642f4434561e4bc6c3eb Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 17 Oct 2024 19:57:18 +0200 Subject: [PATCH] Nav: added io.ConfigNavEscapeClearFocusItem. (#8059, #2048, #1074, #3200) --- docs/CHANGELOG.txt | 11 ++++++++--- docs/TODO.txt | 4 ++-- imgui.cpp | 9 ++++++--- imgui.h | 5 +++-- imgui_demo.cpp | 2 ++ imgui_internal.h | 4 +++- 6 files changed, 24 insertions(+), 11 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 373c12f70..129709152 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,8 +43,8 @@ Breaking changes: - The typedef for ImTextureID now defaults to ImU64 instead of void*. (#1641) - This removes the requirement to redefine it for backends which are e.g. storing - descriptor sets or other 64-bits structures when building on 32-bits archs. - It therefore simplify various building scripts/helpers. + descriptor sets or other 64-bits structures when building on 32-bits archs + (namely our DX12 and Vulkan backends). It therefore simplify various building scripts/helpers. - You may have compile-time issues if you were casting to 'void*' instead of 'ImTextureID' when passing your types to functions taking ImTextureID values, e.g. ImGui::Image(). In doubt it is almost always better to do an intermediate intptr_t cast, since it @@ -67,7 +67,12 @@ Other changes: state to draw callbacks. (#6969, #5834, #7468, #3590) - IO: WantCaptureKeyboard is never set when ImGuiConfigFlags_NoKeyboard is enabled. (#4921) - Error Handling: turned a few more functions into recoverable errors. (#1651) -- Nav: added io.ConfigNavEscapeClearFocusWindow to clear focused window on Escape. (#3200) +- Nav: added io.ConfigNavEscapeClearFocusItem and io.ConfigNavEscapeClearFocusWindow to change + how pressing Escape affects navigation. (#8059, #2048, #1074, #3200) + - Set io.ConfigNavEscapeClearFocusItem = true (default) to clear focused item and highlight. + - Set io.ConfigNavEscapeClearFocusItem = false for Escape to not have a specific effect. + - Set io.ConfigNavEscapeClearFocusWindow = true to completely unfocus the dear imgui window, + is for some reason your app relies on imgui focus to take other decisions. - Nav: pressing escape to hide nav highlight doesn't clear location from when ctrl+tabbing back into same window later. - Nav: fixed Ctrl+Tab so when starting with no focused window it starts from the top-most diff --git a/docs/TODO.txt b/docs/TODO.txt index e61501d78..dd98d18b1 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -275,13 +275,13 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - nav: some features such as PageUp/Down/Home/End should probably work without ImGuiConfigFlags_NavEnableKeyboard? (where do we draw the line? how about CTRL+Tab) ! nav: never clear NavId on some setup (e.g. gamepad centric) - - nav: there's currently no way to completely clear focus with the keyboard. depending on patterns used by the application to dispatch inputs, it may be desirable. - nav: Home/End behavior when navigable item is not fully visible at the edge of scrolling? should be backtrack to keep item into view? - nav: NavScrollToBringItemIntoView() with item bigger than view should focus top-right? Repro: using Nav in "About Window" - - nav: wrap around logic to allow e.g. grid based layout (pressing NavRight on the right-most element would go to the next row, etc.). see internal's NavMoveRequestTryWrapping(). + - nav: expose wrap around flags/logic to allow e.g. grid based layout (pressing NavRight on the right-most element would go to the next row, etc.). see internal's NavMoveRequestTryWrapping(). - nav: patterns to make it possible for arrows key to update selection (see JustMovedTo in range_select branch) - nav: restore/find nearest NavId when current one disappear (e.g. pressed a button that disappear, or perhaps auto restoring when current button change name) - nav: SetItemDefaultFocus() level of priority, so widget like Selectable when inside a popup could claim a low-priority default focus on the first selected iem + - nav: holding space to repeat a button doesn't show button activated during hold. - nav: NavFlattened: init requests don't work properly on flattened siblings. - nav: NavFlattened: pageup/pagedown/home/end don't work properly on flattened siblings. - nav: NavFlattened: ESC on a flattened child should select something. diff --git a/imgui.cpp b/imgui.cpp index 182bd2162..773272e2c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1409,6 +1409,7 @@ ImGuiIO::ImGuiIO() ConfigNavSwapGamepadButtons = false; ConfigNavMoveSetMousePos = false; ConfigNavCaptureKeyboard = true; + ConfigNavEscapeClearFocusItem = true; ConfigNavEscapeClearFocusWindow = false; ConfigInputTrickleEventQueue = true; ConfigInputTextCursorBlink = true; @@ -13376,11 +13377,13 @@ static void ImGui::NavUpdateCancelRequest() { // Clear NavLastId for popups but keep it for regular child window so we can leave one and come back where we were // FIXME-NAV: This should happen on window appearing. - if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup)))// || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow))) - g.NavWindow->NavLastIds[0] = 0; + if (g.IO.ConfigNavEscapeClearFocusItem || g.IO.ConfigNavEscapeClearFocusWindow) + if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup)))// || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow))) + g.NavWindow->NavLastIds[0] = 0; // Clear nav focus - g.NavId = 0; + if (g.IO.ConfigNavEscapeClearFocusItem || g.IO.ConfigNavEscapeClearFocusWindow) + g.NavId = 0; if (g.IO.ConfigNavEscapeClearFocusWindow) FocusWindow(NULL); } diff --git a/imgui.h b/imgui.h index 4ea730626..641f1d54d 100644 --- a/imgui.h +++ b/imgui.h @@ -2250,7 +2250,8 @@ struct ImGuiIO bool ConfigNavSwapGamepadButtons; // = false // Swap Activate<>Cancel (A<>B) buttons, matching typical "Nintendo/Japanese style" gamepad layout. bool ConfigNavMoveSetMousePos; // = false // Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult. Will update io.MousePos and set io.WantSetMousePos=true. bool ConfigNavCaptureKeyboard; // = true // Sets io.WantCaptureKeyboard when io.NavActive is set. - bool ConfigNavEscapeClearFocusWindow;// = false // Pressing Escape (when no item is active, no popup open etc.) clears focused window + navigation id/highlight. + bool ConfigNavEscapeClearFocusItem; // = true // Pressing Escape can clear focused item + navigation id/highlight. Set to false if you want to always keep highlight on. + bool ConfigNavEscapeClearFocusWindow;// = false // Pressing Escape can clear focused window as well (super set of io.ConfigNavEscapeClearFocusItem). bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates. bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting). bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will keep item active and select contents (single-line only). @@ -2367,7 +2368,7 @@ struct ImGuiIO bool WantSetMousePos; // MousePos has been altered, backend should reposition mouse on next frame. Rarely used! Set only when io.ConfigNavMoveSetMousePos is enabled. bool WantSaveIniSettings; // When manual .ini load/save is active (io.IniFilename == NULL), this will be set to notify your application that you can call SaveIniSettingsToMemory() and save yourself. Important: clear io.WantSaveIniSettings yourself after saving! bool NavActive; // Keyboard/Gamepad navigation is currently allowed (will handle ImGuiKey_NavXXX events) = a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag. - bool NavVisible; // Keyboard/Gamepad navigation is visible and allowed (will handle ImGuiKey_NavXXX events). + bool NavVisible; // Keyboard/Gamepad navigation highlight is visible and allowed (will handle ImGuiKey_NavXXX events). float Framerate; // Estimate of application framerate (rolling average over 60 frames, based on io.DeltaTime), in frame per second. Solely for convenience. Slow applications may not want to use a moving average or may want to reset underlying buffers occasionally. int MetricsRenderVertices; // Vertices output during last call to Render() int MetricsRenderIndices; // Indices output during last call to Render() = number of triangles * 3 diff --git a/imgui_demo.cpp b/imgui_demo.cpp index dca674054..63f6d15d1 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -532,6 +532,8 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::Checkbox("io.ConfigNavMoveSetMousePos", &io.ConfigNavMoveSetMousePos); ImGui::SameLine(); HelpMarker("Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult"); ImGui::Checkbox("io.ConfigNavCaptureKeyboard", &io.ConfigNavCaptureKeyboard); + ImGui::Checkbox("io.ConfigNavEscapeClearFocusItem", &io.ConfigNavEscapeClearFocusItem); + ImGui::SameLine(); HelpMarker("Pressing Escape clears focused item."); ImGui::Checkbox("io.ConfigNavEscapeClearFocusWindow", &io.ConfigNavEscapeClearFocusWindow); ImGui::SameLine(); HelpMarker("Pressing Escape clears focused window."); diff --git a/imgui_internal.h b/imgui_internal.h index bf7759f7b..bc00d0c28 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1600,7 +1600,7 @@ struct ImGuiNavItemData void Clear() { Window = NULL; ID = FocusScopeId = 0; ItemFlags = 0; SelectionUserData = -1; DistBox = DistCenter = DistAxial = FLT_MAX; } }; -// Storage for PushFocusScope() +// Storage for PushFocusScope(), g.FocusScopeStack[], g.NavFocusRoute[] struct ImGuiFocusScopeData { ImGuiID ID; @@ -3223,6 +3223,8 @@ namespace ImGui IMGUI_API void RenderDragDropTargetRect(const ImRect& bb, const ImRect& item_clip_rect); // Typing-Select API + // (provide Windows Explorer style "select items by typing partial name" + "cycle through items by typing same letter" feature) + // (this is currently not documented nor used by main library, but should work. See "widgets_typingselect" in imgui_test_suite for usage code. Please let us know if you use this!) IMGUI_API ImGuiTypingSelectRequest* GetTypingSelectRequest(ImGuiTypingSelectFlags flags = ImGuiTypingSelectFlags_None); IMGUI_API int TypingSelectFindMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx); IMGUI_API int TypingSelectFindNextSingleCharMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx);