From baea25e657b0798f2b69fb19ef3109209ec1441c Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 25 Oct 2022 15:07:00 +0200 Subject: [PATCH 01/13] Drag and Drop: extracted a RenderDragDropTargetRect() function (#1603) --- imgui.cpp | 7 ++++++- imgui_internal.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index c81ecf68..769c6a33 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11618,7 +11618,6 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop } // Render default drop visuals - // FIXME-DRAGDROP: Settle on a proper default visuals for drop target. payload.Preview = was_accepted_previously; flags |= (g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect); // Source can also inhibit the preview (useful for external sources that live for 1 frame) if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview) @@ -11632,6 +11631,12 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop return &payload; } +// FIXME-DRAGDROP: Settle on a proper default visuals for drop target. +void ImGui::RenderDragDropTargetRect(const ImRect& bb) +{ + GetWindowDrawList()->AddRect(bb.Min - ImVec2(3.5f, 3.5f), bb.Max + ImVec2(3.5f, 3.5f), GetColorU32(ImGuiCol_DragDropTarget), 0.0f, 0, 2.0f); +} + const ImGuiPayload* ImGui::GetDragDropPayload() { ImGuiContext& g = *GImGui; diff --git a/imgui_internal.h b/imgui_internal.h index 88c420ea..9fd0ede2 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2772,6 +2772,7 @@ namespace ImGui IMGUI_API bool BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id); IMGUI_API void ClearDragDrop(); IMGUI_API bool IsDragDropPayloadBeingAccepted(); + IMGUI_API void RenderDragDropTargetRect(const ImRect& bb); // Internal Columns API (this is not exposed because we will encourage transitioning to the Tables API) IMGUI_API void SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect); From 9db6b1a0d9102744818741ae5a6c7f9498aff343 Mon Sep 17 00:00:00 2001 From: Teselka Date: Tue, 25 Oct 2022 13:39:27 +0300 Subject: [PATCH 02/13] Backends: Win32: minor tidying up. (#5819) --- backends/imgui_impl_win32.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/backends/imgui_impl_win32.cpp b/backends/imgui_impl_win32.cpp index bc3ab535..a4660afd 100644 --- a/backends/imgui_impl_win32.cpp +++ b/backends/imgui_impl_win32.cpp @@ -88,10 +88,10 @@ struct ImGui_ImplWin32_Data INT64 Time; INT64 TicksPerSecond; ImGuiMouseCursor LastMouseCursor; - bool HasGamepad; - bool WantUpdateHasGamepad; #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD + bool HasGamepad; + bool WantUpdateHasGamepad; HMODULE XInputDLL; PFN_XInputGetCapabilities XInputGetCapabilities; PFN_XInputGetState XInputGetState; @@ -129,7 +129,6 @@ bool ImGui_ImplWin32_Init(void* hwnd) io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) bd->hWnd = (HWND)hwnd; - bd->WantUpdateHasGamepad = true; bd->TicksPerSecond = perf_frequency; bd->Time = perf_counter; bd->LastMouseCursor = ImGuiMouseCursor_COUNT; @@ -139,6 +138,7 @@ bool ImGui_ImplWin32_Init(void* hwnd) // Dynamically load XInput library #ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD + bd->WantUpdateHasGamepad = true; const char* xinput_dll_names[] = { "xinput1_4.dll", // Windows 8+ @@ -634,8 +634,10 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA return 1; return 0; case WM_DEVICECHANGE: +#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD if ((UINT)wParam == DBT_DEVNODES_CHANGED) bd->WantUpdateHasGamepad = true; +#endif return 0; } return 0; From a61bbdc239157cfd1d512667b80439b5b17daed6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 26 Oct 2022 22:22:53 +0200 Subject: [PATCH 03/13] Commented out redirecting OpenPopupContextItem() which was briefly the name of OpenPopupOnItemClick() from 1.77 to 1.79. --- docs/CHANGELOG.txt | 3 ++- imgui.cpp | 1 + imgui.h | 20 +++++++++++--------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 21706b3c..1fc0a0e6 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -79,11 +79,12 @@ Breaking changes: - Removed the bizarre legacy default argument for 'TreePush(const void* ptr = NULL)'. (#1057) Must always pass a pointer value explicitly, NULL/nullptr is ok but require cast, e.g. TreePush((void*)nullptr); If you used TreePush() replace with TreePush((void*)NULL); - - Commented out redirecting functions/enums names that were marked obsolete in 1.77 and 1.78 (June 2020): (#3361) + - Commented out redirecting functions/enums names that were marked obsolete in 1.77 and 1.79 (August 2020): (#3361) - DragScalar(), DragScalarN(), DragFloat(), DragFloat2(), DragFloat3(), DragFloat4() - SliderScalar(), SliderScalarN(), SliderFloat(), SliderFloat2(), SliderFloat3(), SliderFloat4() - For old signatures ending with (..., const char* format, float power = 1.0f) -> use (..., format ImGuiSliderFlags_Logarithmic) if power != 1.0f. - BeginPopupContextWindow(const char*, ImGuiMouseButton, bool) -> use BeginPopupContextWindow(const char*, ImGuiPopupFlags) + - OpenPopupContextItem() (briefly existed from 1.77 to 1.79) -> use OpenPopupOnItemClick() - Obsoleted using SetCursorPos()/SetCursorScreenPos() to extend parent window/cell boundaries. (#5548) This relates to when moving the cursor position beyond current boundaries WITHOUT submitting an item. - Previously this would make the window content size ~200x200: diff --git a/imgui.cpp b/imgui.cpp index 769c6a33..0e056abb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -384,6 +384,7 @@ CODE When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files. You can read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2022/10/26 (1.89) - commented out redirecting OpenPopupContextItem() which was briefly the name of OpenPopupOnItemClick() from 1.77 to 1.79. - 2022/10/12 (1.89) - removed runtime patching of invalid "%f"/"%0.f" format strings for DragInt()/SliderInt(). This was obsoleted in 1.61 (May 2018). See 1.61 changelog for details. - 2022/09/26 (1.89) - renamed and merged keyboard modifiers key enums and flags into a same set. Kept inline redirection enums (will obsolete). - ImGuiKey_ModCtrl and ImGuiModFlags_Ctrl -> ImGuiMod_Ctrl diff --git a/imgui.h b/imgui.h index f30e813b..5ae2158c 100644 --- a/imgui.h +++ b/imgui.h @@ -2964,21 +2964,21 @@ namespace ImGui // OBSOLETED in 1.89 (from August 2022) IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0, 0, 0, 0), const ImVec4& tint_col = ImVec4(1, 1, 1, 1)); // Use new ImageButton() signature (explicit item id, regular FramePadding) // OBSOLETED in 1.88 (from May 2022) - static inline void CaptureKeyboardFromApp(bool want_capture_keyboard = true) { SetNextFrameWantCaptureKeyboard(want_capture_keyboard); } // Renamed as name was misleading + removed default value. - static inline void CaptureMouseFromApp(bool want_capture_mouse = true) { SetNextFrameWantCaptureMouse(want_capture_mouse); } // Renamed as name was misleading + removed default value. + static inline void CaptureKeyboardFromApp(bool want_capture_keyboard = true) { SetNextFrameWantCaptureKeyboard(want_capture_keyboard); } // Renamed as name was misleading + removed default value. + static inline void CaptureMouseFromApp(bool want_capture_mouse = true) { SetNextFrameWantCaptureMouse(want_capture_mouse); } // Renamed as name was misleading + removed default value. // OBSOLETED in 1.86 (from November 2021) IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // Calculate coarse clipping for large list of evenly sized items. Prefer using ImGuiListClipper. // OBSOLETED in 1.85 (from August 2021) - static inline float GetWindowContentRegionWidth() { return GetWindowContentRegionMax().x - GetWindowContentRegionMin().x; } + static inline float GetWindowContentRegionWidth() { return GetWindowContentRegionMax().x - GetWindowContentRegionMin().x; } // OBSOLETED in 1.81 (from February 2021) IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // Helper to calculate size from items_count and height_in_items - static inline bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0, 0)) { return BeginListBox(label, size); } - static inline void ListBoxFooter() { EndListBox(); } - // OBSOLETED in 1.79 (from August 2020) - static inline void OpenPopupContextItem(const char* str_id = NULL, ImGuiMouseButton mb = 1) { OpenPopupOnItemClick(str_id, mb); } // Bool return value removed. Use IsWindowAppearing() in BeginPopup() instead. Renamed in 1.77, renamed back in 1.79. Sorry! + static inline bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0, 0)) { return BeginListBox(label, size); } + static inline void ListBoxFooter() { EndListBox(); } // Some of the older obsolete names along with their replacement (commented out so they are not reported in IDE) - // [OBSOLETED in 1.78 (from June 2020] Old drag/sliders functions that took a 'float power > 1.0f' argument instead of ImGuiSliderFlags_Logarithmic. See github.com/ocornut/imgui/issues/3361 for details. + //-- OBSOLETED in 1.79 (from August 2020) + //static inline void OpenPopupContextItem(const char* str_id = NULL, ImGuiMouseButton mb = 1) { OpenPopupOnItemClick(str_id, mb); } // Bool return value removed. Use IsWindowAppearing() in BeginPopup() instead. Renamed in 1.77, renamed back in 1.79. Sorry! + //-- OBSOLETED in 1.78 (from June 2020): Old drag/sliders functions that took a 'float power > 1.0f' argument instead of ImGuiSliderFlags_Logarithmic. See github.com/ocornut/imgui/issues/3361 for details. //IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min, const void* p_max, const char* format, float power = 1.0f) // OBSOLETED in 1.78 (from June 2020) //IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min, const void* p_max, const char* format, float power = 1.0f); // OBSOLETED in 1.78 (from June 2020) //IMGUI_API bool SliderScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_min, const void* p_max, const char* format, float power = 1.0f); // OBSOLETED in 1.78 (from June 2020) @@ -2991,7 +2991,7 @@ namespace ImGui //static inline bool SliderFloat2(const char* label, float v[2], float v_min, float v_max, const char* format, float power = 1.0f) { return SliderScalarN(label, ImGuiDataType_Float, v, 2, &v_min, &v_max, format, power); } // OBSOLETED in 1.78 (from June 2020) //static inline bool SliderFloat3(const char* label, float v[3], float v_min, float v_max, const char* format, float power = 1.0f) { return SliderScalarN(label, ImGuiDataType_Float, v, 3, &v_min, &v_max, format, power); } // OBSOLETED in 1.78 (from June 2020) //static inline bool SliderFloat4(const char* label, float v[4], float v_min, float v_max, const char* format, float power = 1.0f) { return SliderScalarN(label, ImGuiDataType_Float, v, 4, &v_min, &v_max, format, power); } // OBSOLETED in 1.78 (from June 2020) - // [OBSOLETED in 1.77 and before] + //-- OBSOLETED in 1.77 and before //static inline bool BeginPopupContextWindow(const char* str_id, ImGuiMouseButton mb, bool over_items) { return BeginPopupContextWindow(str_id, mb | (over_items ? 0 : ImGuiPopupFlags_NoOpenOverItems)); } // OBSOLETED in 1.77 (from June 2020) //static inline void TreeAdvanceToLabelPos() { SetCursorPosX(GetCursorPosX() + GetTreeNodeToLabelSpacing()); } // OBSOLETED in 1.72 (from July 2019) //static inline void SetNextTreeNodeOpen(bool open, ImGuiCond cond = 0) { SetNextItemOpen(open, cond); } // OBSOLETED in 1.71 (from June 2019) @@ -2999,6 +2999,7 @@ namespace ImGui //static inline ImDrawList* GetOverlayDrawList() { return GetForegroundDrawList(); } // OBSOLETED in 1.69 (from Mar 2019) //static inline void SetScrollHere(float ratio = 0.5f) { SetScrollHereY(ratio); } // OBSOLETED in 1.66 (from Nov 2018) //static inline bool IsItemDeactivatedAfterChange() { return IsItemDeactivatedAfterEdit(); } // OBSOLETED in 1.63 (from Aug 2018) + //-- OBSOLETED in 1.60 and before //static inline bool IsAnyWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_AnyWindow); } // OBSOLETED in 1.60 (from Apr 2018) //static inline bool IsAnyWindowHovered() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); } // OBSOLETED in 1.60 (between Dec 2017 and Apr 2018) //static inline void ShowTestWindow() { return ShowDemoWindow(); } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017) @@ -3014,6 +3015,7 @@ namespace ImGui //static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // OBSOLETED in 1.51 (between Jun 2017 and Aug 2017): This was misleading and partly broken. You probably want to use the io.WantCaptureMouse flag instead. //static inline bool IsMouseHoveringAnyWindow() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); } // OBSOLETED in 1.51 (between Jun 2017 and Aug 2017) //static inline bool IsMouseHoveringWindow() { return IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); } // OBSOLETED in 1.51 (between Jun 2017 and Aug 2017) + //-- OBSOLETED in 1.50 and before //static inline bool CollapsingHeader(char* label, const char* str_id, bool framed = true, bool default_open = false) { return CollapsingHeader(label, (default_open ? (1 << 5) : 0)); } // OBSOLETED in 1.49 //static inline ImFont*GetWindowFont() { return GetFont(); } // OBSOLETED in 1.48 //static inline float GetWindowFontSize() { return GetFontSize(); } // OBSOLETED in 1.48 From a241dc7990b631fde6575771173c2442d43d2812 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 27 Oct 2022 20:17:19 +0200 Subject: [PATCH 04/13] IO: Fixed AddFocusEvent(false) to also clear MouseDown[] state. (#4921) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 3 +++ 2 files changed, 4 insertions(+) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1fc0a0e6..f97cdf19 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -142,6 +142,7 @@ Other Changes: - IO: Added ImGuiKey_MouseXXX aliases for mouse buttons/wheel so all operations done on ImGuiKey can apply to mouse data as well. (#4921) - IO: Filter duplicate input events during the AddXXX() calls. (#5599, #4921) +- IO: Fixed AddFocusEvent(false) to also clear MouseDown[] state. (#4921) - Menus: Fixed incorrect sub-menu parent association when opening a menu by closing another. Among other things, it would accidentally break part of the closing heuristic logic when moving towards a sub-menu. (#2517, #5614). [@rokups] diff --git a/imgui.cpp b/imgui.cpp index 0e056abb..979384a5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1303,6 +1303,9 @@ void ImGuiIO::ClearInputKeys() } KeyCtrl = KeyShift = KeyAlt = KeySuper = false; KeyMods = ImGuiMod_None; + MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + memset(MouseDown, 0, sizeof(MouseDown)); + MouseWheel = MouseWheelH = 0.0f; } static ImGuiInputEvent* FindLatestInputEvent(ImGuiInputEventType type, int arg = -1) From 22bcfca70055be41b12a3946132af58d4d736a58 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 28 Oct 2022 20:01:20 +0200 Subject: [PATCH 05/13] IO: Clear AppFocusLost in EndFrame() in order to allow backend or application code to poll and react to it + Amend a241dc7 with the same clearing of MouseDownDuration[] as keyboard ones. --- imgui.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 979384a5..d5486d64 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1304,7 +1304,11 @@ void ImGuiIO::ClearInputKeys() KeyCtrl = KeyShift = KeyAlt = KeySuper = false; KeyMods = ImGuiMod_None; MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - memset(MouseDown, 0, sizeof(MouseDown)); + for (int n = 0; n < IM_ARRAYSIZE(MouseDown); n++) + { + MouseDown[n] = false; + MouseDownDuration[n] = MouseDownDurationPrev[n] = -1.0f; + } MouseWheel = MouseWheelH = 0.0f; } @@ -5122,6 +5126,7 @@ void ImGui::EndFrame() g.IO.Fonts->Locked = false; // Clear Input data for next frame + g.IO.AppFocusLost = false; g.IO.MouseWheel = g.IO.MouseWheelH = 0.0f; g.IO.InputQueueCharacters.resize(0); @@ -8283,12 +8288,11 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs) g.InputEventsQueue.erase(g.InputEventsQueue.Data, g.InputEventsQueue.Data + event_n); // Clear buttons state when focus is lost - // (this is useful so e.g. releasing Alt after focus loss on Alt-Tab doesn't trigger the Alt menu toggle) + // - this is useful so e.g. releasing Alt after focus loss on Alt-Tab doesn't trigger the Alt menu toggle. + // - we clear in EndFrame() and not now in order allow application/user code polling this flag + // (e.g. custom backend may want to clear additional data, custom widgets may want to react with a "canceling" event). if (g.IO.AppFocusLost) - { g.IO.ClearInputKeys(); - g.IO.AppFocusLost = false; - } } From c2694ef75e2b626ebf52493f4a1282d500d33bbb Mon Sep 17 00:00:00 2001 From: Rewtio Date: Sun, 30 Oct 2022 05:09:13 +0700 Subject: [PATCH 06/13] Examples: Android: Using LoadIniSettingsFromMemory() / SaveIniSettingsToMemory() to save in appropriate location for Android. (#5836) --- docs/CHANGELOG.txt | 1 + examples/example_android_opengl3/main.cpp | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index f97cdf19..b10e57dc 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -181,6 +181,7 @@ Other Changes: - Demo: Fixed Log & Console from losing scrolling position with Auto-Scroll when child is clipped. (#5721) - Examples: Added all SDL examples to default VS solution. - Examples: Win32: Always use RegisterClassW() to ensure windows are Unicode. (#5725) +- Examples: Android: Enable .ini file loading/saving into application internal data folder. (#5836) [@rewtio] - Backends: GLFW: Honor GLFW_CURSOR_DISABLED by not setting mouse position. (#5625) [@scorpion-26] - Backends: GLFW: Add glfwGetError() call on GLFW 3.3 to inhibit missing mouse cursor errors. (#5785) [@mitchellh] - Backends: SDL: Disable SDL 2.0.22 new "auto capture" which prevents drag and drop across windows diff --git a/examples/example_android_opengl3/main.cpp b/examples/example_android_opengl3/main.cpp index 4237e408..0dab5d0c 100644 --- a/examples/example_android_opengl3/main.cpp +++ b/examples/example_android_opengl3/main.cpp @@ -9,6 +9,7 @@ #include #include #include +#include // Data static EGLDisplay g_EglDisplay = EGL_NO_DISPLAY; @@ -17,6 +18,7 @@ static EGLContext g_EglContext = EGL_NO_CONTEXT; static struct android_app* g_App = NULL; static bool g_Initialized = false; static char g_LogTag[] = "ImGuiExample"; +static std::string g_IniFilename = ""; // Forward declarations of helper functions static int ShowSoftKeyboardInput(); @@ -70,9 +72,10 @@ void init(struct android_app* app) ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); - // Disable loading/saving of .ini file from disk. - // FIXME: Consider using LoadIniSettingsFromMemory() / SaveIniSettingsToMemory() to save in appropriate location for Android. - io.IniFilename = NULL; + // Redirect loading/saving of .ini file to our location. + // Make sure 'g_IniFilename' persists while we use Dear ImGui. + g_IniFilename = std::string(app->activity->internalDataPath) + "/imgui.ini"; + io.IniFilename = g_IniFilename.c_str();; // Setup Dear ImGui style ImGui::StyleColorsDark(); From 86f2af2bc7a0e828f9aebd6d03d0547db45d663f Mon Sep 17 00:00:00 2001 From: Akira Maezawa Date: Wed, 2 Nov 2022 01:52:20 +0900 Subject: [PATCH 07/13] Backends: OSX: Fixed mouse coordinate before clicking on the host window. (#5842) --- backends/imgui_impl_osx.mm | 3 +++ docs/CHANGELOG.txt | 1 + 2 files changed, 4 insertions(+) diff --git a/backends/imgui_impl_osx.mm b/backends/imgui_impl_osx.mm index 054776ff..2505bbd3 100644 --- a/backends/imgui_impl_osx.mm +++ b/backends/imgui_impl_osx.mm @@ -23,6 +23,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-11-02: Fixed mouse coordinates before clicking the host window. // 2022-10-06: Fixed mouse inputs on flipped views. // 2022-09-26: Inputs: Renamed ImGuiKey_ModXXX introduced in 1.87 to ImGuiMod_XXX (old names still supported). // 2022-05-03: Inputs: Removed ImGui_ImplOSX_HandleEvent() from backend API in favor of backend automatically handling event capture. @@ -631,6 +632,8 @@ static bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view) if (event.type == NSEventTypeMouseMoved || event.type == NSEventTypeLeftMouseDragged || event.type == NSEventTypeRightMouseDragged || event.type == NSEventTypeOtherMouseDragged) { NSPoint mousePoint = event.locationInWindow; + if (event.window == nil) + mousePoint = [[view window] convertPointFromScreen:mousePoint]; mousePoint = [view convertPoint:mousePoint fromView:nil]; if ([view isFlipped]) mousePoint = NSMakePoint(mousePoint.x, mousePoint.y); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b10e57dc..630a1d81 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -193,6 +193,7 @@ Other Changes: - Backends: Metal: Update deprecated property 'sampleCount'->'rasterSampleCount'. (#5603) [@dcvz] - Backends: Vulkan: Added experimental ImGui_ImplVulkan_RemoveTexture() for api symetry. (#914, #5738). - Backends: OSX: Fixed mouse inputs on flipped views. (#5756) [@Nemirtingas] +- Backends: OSX: Fixed mouse coordinate before clicking on the host window. (#5842) [@maezawa-akira] - Backends: OSX: Fixes to support full app creation in C++. (#5403) [@stack] From 6e9dfe1de1131635128e01cc6ae2420c781d88d1 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 2 Nov 2022 12:36:22 +0100 Subject: [PATCH 08/13] Window: Auto-fit size takes account of work rectangle (menu bars eating from viewport). (#5843) --- docs/CHANGELOG.txt | 1 + imgui.cpp | 3 +-- imgui.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 630a1d81..a979cc8a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -138,6 +138,7 @@ Other Changes: - Tabs: Enforcing minimum size of 1.0f, fixed asserting on zero-tab widths. (#5572) - Window: Fixed a potential crash when appending to a child window. (#5515, #3496, #4797) [@rokups] - Window: Fixed an issue where uncollapsed a window would show a scrollbar for a frame. +- Window: Auto-fit size takes account of work rectangle (menu bars eating from viewport). (#5843) - IO: Added ImGuiMod_Shortcut which is ImGuiMod_Super on Mac and ImGuiMod_Ctrl otherwise. (#456) - IO: Added ImGuiKey_MouseXXX aliases for mouse buttons/wheel so all operations done on ImGuiKey can apply to mouse data as well. (#4921) diff --git a/imgui.cpp b/imgui.cpp index d5486d64..305a8030 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5732,8 +5732,7 @@ static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window, const ImVec2& size_cont if (is_popup || is_menu) // Popups and menus bypass style.WindowMinSize by default, but we give then a non-zero minimum size to facilitate understanding problematic cases (e.g. empty popups) size_min = ImMin(size_min, ImVec2(4.0f, 4.0f)); - // FIXME-VIEWPORT-WORKAREA: May want to use GetWorkSize() instead of Size depending on the type of windows? - ImVec2 avail_size = ImGui::GetMainViewport()->Size; + ImVec2 avail_size = ImGui::GetMainViewport()->WorkSize; ImVec2 size_auto_fit = ImClamp(size_desired, size_min, ImMax(size_min, avail_size - style.DisplaySafeAreaPadding * 2.0f)); // When the window cannot fit all contents (either because of constraints, either because screen is too small), diff --git a/imgui.h b/imgui.h index 5ae2158c..8fa9a65a 100644 --- a/imgui.h +++ b/imgui.h @@ -23,7 +23,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM > 12345') #define IMGUI_VERSION "1.89 WIP" -#define IMGUI_VERSION_NUM 18833 +#define IMGUI_VERSION_NUM 18834 #define IMGUI_HAS_TABLE /* From 90e9465fa579efcac20f250433ff6307980d9bbc Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 2 Nov 2022 12:36:41 +0100 Subject: [PATCH 09/13] Window: Fixed position not being clamped while auto-resizing (#5843) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a979cc8a..ffc98031 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -139,6 +139,8 @@ Other Changes: - Window: Fixed a potential crash when appending to a child window. (#5515, #3496, #4797) [@rokups] - Window: Fixed an issue where uncollapsed a window would show a scrollbar for a frame. - Window: Auto-fit size takes account of work rectangle (menu bars eating from viewport). (#5843) +- Window: Fixed position not being clamped while auto-resizing (fixes appearing windows without + .ini data from moving for a frame when using io.ConfigWindowsMoveFromTitleBarOnly). (#5843) - IO: Added ImGuiMod_Shortcut which is ImGuiMod_Super on Mac and ImGuiMod_Ctrl otherwise. (#456) - IO: Added ImGuiKey_MouseXXX aliases for mouse buttons/wheel so all operations done on ImGuiKey can apply to mouse data as well. (#4921) diff --git a/imgui.cpp b/imgui.cpp index 305a8030..8c9121bd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5987,7 +5987,7 @@ static bool ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& s return ret_auto_fit; } -static inline void ClampWindowRect(ImGuiWindow* window, const ImRect& visibility_rect) +static inline void ClampWindowPos(ImGuiWindow* window, const ImRect& visibility_rect) { ImGuiContext& g = *GImGui; ImVec2 size_for_clamping = window->Size; @@ -6576,9 +6576,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Clamp position/size so window stays visible within its viewport or monitor // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing. - if (!window_pos_set_by_api && !(flags & ImGuiWindowFlags_ChildWindow) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0) + if (!window_pos_set_by_api && !(flags & ImGuiWindowFlags_ChildWindow)) if (viewport_rect.GetWidth() > 0.0f && viewport_rect.GetHeight() > 0.0f) - ClampWindowRect(window, visibility_rect); + ClampWindowPos(window, visibility_rect); window->Pos = ImFloor(window->Pos); // Lock window rounding for the frame (so that altering them doesn't cause inconsistencies) From 1eac0024c0ca7f4a903875794fbdfac0094e4228 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 3 Nov 2022 18:23:42 +0100 Subject: [PATCH 10/13] InputText: copy and select all shortcuts don't need repeat (tho it was harmless0 --- imgui_demo.cpp | 2 +- imgui_widgets.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index a323e8e8..4639a859 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -5767,7 +5767,7 @@ static void ShowDemoWindowInputs() const ImGuiKey key_first = (ImGuiKey)0; //ImGui::Text("Legacy raw:"); for (ImGuiKey key = key_first; key < ImGuiKey_COUNT; key++) { if (io.KeysDown[key]) { ImGui::SameLine(); ImGui::Text("\"%s\" %d", ImGui::GetKeyName(key), key); } } #endif - ImGui::Text("Keys down:"); for (ImGuiKey key = key_first; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key)) continue; if (ImGui::IsKeyDown(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d (%.02f secs)", ImGui::GetKeyName(key), key, ImGui::GetKeyData(key)->DownDuration); } } + ImGui::Text("Keys down:"); for (ImGuiKey key = key_first; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key)) continue; if (ImGui::IsKeyDown(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d (%.02f)", ImGui::GetKeyName(key), key, ImGui::GetKeyData(key)->DownDuration); } } ImGui::Text("Keys pressed:"); for (ImGuiKey key = key_first; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key)) continue; if (ImGui::IsKeyPressed(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d", ImGui::GetKeyName(key), key); } } ImGui::Text("Keys released:"); for (ImGuiKey key = key_first; key < ImGuiKey_COUNT; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key)) continue; if (ImGui::IsKeyReleased(key)) { ImGui::SameLine(); ImGui::Text("\"%s\" %d", ImGui::GetKeyName(key), key); } } ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 51675caa..746c6364 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4282,11 +4282,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ const bool is_shortcut_key = g.IO.ConfigMacOSXBehaviors ? (io.KeyMods == ImGuiMod_Super) : (io.KeyMods == ImGuiMod_Ctrl); const bool is_cut = ((is_shortcut_key && IsKeyPressed(ImGuiKey_X)) || (is_shift_key_only && IsKeyPressed(ImGuiKey_Delete))) && !is_readonly && !is_password && (!is_multiline || state->HasSelection()); - const bool is_copy = ((is_shortcut_key && IsKeyPressed(ImGuiKey_C)) || (is_ctrl_key_only && IsKeyPressed(ImGuiKey_Insert))) && !is_password && (!is_multiline || state->HasSelection()); + const bool is_copy = ((is_shortcut_key && IsKeyPressed(ImGuiKey_C, false)) || (is_ctrl_key_only && IsKeyPressed(ImGuiKey_Insert, false))) && !is_password && (!is_multiline || state->HasSelection()); const bool is_paste = ((is_shortcut_key && IsKeyPressed(ImGuiKey_V)) || (is_shift_key_only && IsKeyPressed(ImGuiKey_Insert))) && !is_readonly; const bool is_undo = ((is_shortcut_key && IsKeyPressed(ImGuiKey_Z)) && !is_readonly && is_undoable); const bool is_redo = ((is_shortcut_key && IsKeyPressed(ImGuiKey_Y)) || (is_osx_shift_shortcut && IsKeyPressed(ImGuiKey_Z))) && !is_readonly && is_undoable; - const bool is_select_all = is_shortcut_key && IsKeyPressed(ImGuiKey_A); + const bool is_select_all = is_shortcut_key && IsKeyPressed(ImGuiKey_A, false); // 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 nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0; From 9f66a3a9eda865cd0e3e9d4563e9fe92a8a8785d Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 19 Oct 2022 20:54:19 +0200 Subject: [PATCH 11/13] Internals: rework FocusScope system, current scope doesn't need to be in window + child doesn't inherit. Intended as part of work for input routing + blind menu processing shortcuts. Some of this commit will be stripped by next commit. Intent was to sort windows along with focus scope to build a hierarchy, but for our needs we'd need a persistant one, so scrapping the idea. Not squashing this with next commit to keep a bit of history for future references. --- imgui.cpp | 66 ++++++++++++++++++++++++++++------------------- imgui.h | 2 +- imgui_internal.h | 36 +++++++++++++++++++------- imgui_widgets.cpp | 4 +-- 4 files changed, 68 insertions(+), 40 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8c9121bd..ded31fa7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6319,10 +6319,23 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window_stack_data.ParentLastItemDataBackup = g.LastItemData; window_stack_data.StackSizesOnBegin.SetToCurrentState(); g.CurrentWindowStack.push_back(window_stack_data); - g.CurrentWindow = NULL; if (flags & ImGuiWindowFlags_ChildMenu) g.BeginMenuCount++; + // Update ->RootWindow and others pointers (before any possible call to FocusWindow) + if (first_begin_of_the_frame) + { + UpdateWindowParentAndRootLinks(window, flags, parent_window); + window->ParentWindowInBeginStack = parent_window_in_stack; + } + + // Add to focus scope stack - inherited by default by child windows from parent, reset by regular window + //if (window == window->RootWindow && (window->Flags & ImGuiWindowFlags_ChildMenu) == 0) + PushFocusScope(window->ID); + window->NavRootFocusScopeId = g.CurrentFocusScopeId; + g.CurrentWindow = NULL; + + // Add to popup stack if (flags & ImGuiWindowFlags_Popup) { ImGuiPopupData& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size]; @@ -6332,13 +6345,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->PopupId = popup_ref.PopupId; } - // Update ->RootWindow and others pointers (before any possible call to FocusWindow) - if (first_begin_of_the_frame) - { - UpdateWindowParentAndRootLinks(window, flags, parent_window); - window->ParentWindowInBeginStack = parent_window_in_stack; - } - // Process SetNextWindow***() calls // (FIXME: Consider splitting the HasXXX flags into X/Y components bool window_pos_set_by_api = false; @@ -6859,9 +6865,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) SetCurrentWindow(window); } - // Pull/inherit current state - window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : window->GetID("#FOCUSSCOPE"); // Inherit from parent only // -V595 - PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true); // Clear 'accessed' flag last thing (After PushClipRect which will set the flag. We want the flag to stay false when the default "Debug" window is unused) @@ -6939,6 +6942,8 @@ void ImGui::End() if (window->DC.CurrentColumns) EndColumns(); PopClipRect(); // Inner window clip rectangle + //if (window == window->RootWindow && (window->Flags & ImGuiWindowFlags_ChildMenu) == 0) + PopFocusScope(); // Stop logging if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging @@ -7048,7 +7053,7 @@ void ImGui::FocusWindow(ImGuiWindow* window) g.NavMousePosDirty = true; g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId g.NavLayer = ImGuiNavLayer_Main; - g.NavFocusScopeId = 0; + g.NavFocusScopeId = window ? window->NavRootFocusScopeId : 0; g.NavIdIsAlive = false; // Close popups if any @@ -7619,18 +7624,24 @@ void ImGui::ActivateItem(ImGuiID id) void ImGui::PushFocusScope(ImGuiID id) { ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - g.FocusScopeStack.push_back(window->DC.NavFocusScopeIdCurrent); - window->DC.NavFocusScopeIdCurrent = id; + if (g.FocusScopeStackLocked > 0) + return; + ImGuiFocusScope scope; + scope.FocusScopeId = id; + scope.Window = g.CurrentWindow; + g.FocusScopeStack.push_back(scope); + g.CurrentFocusScopeId = scope.FocusScopeId; } void ImGui::PopFocusScope() { ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; + if (g.FocusScopeStackLocked > 0) + return; IM_ASSERT(g.FocusScopeStack.Size > 0); // Too many PopFocusScope() ? - window->DC.NavFocusScopeIdCurrent = g.FocusScopeStack.back(); + IM_ASSERT(g.FocusScopeStack.back().Window == g.CurrentWindow); // Mismatched pop location? g.FocusScopeStack.pop_back(); + g.CurrentFocusScopeId = g.FocusScopeStack.Size ? g.FocusScopeStack.back().FocusScopeId : 0; } // Note: this will likely be called ActivateItem() once we rework our Focus/Activation system! @@ -8509,7 +8520,7 @@ void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo if (log_callback) log_callback(user_data, "Recovered from missing PopStyleVar() in '%s'", window->Name); PopStyleVar(); } - while (g.FocusScopeStack.Size > stack_sizes->SizeOfFocusScopeStack) //-V1044 + while (g.FocusScopeStack.Size > stack_sizes->SizeOfFocusScopeStack + 1) //-V1044 { if (log_callback) log_callback(user_data, "Recovered from missing PopFocusScope() in '%s'", window->Name); PopFocusScope(); @@ -9953,12 +9964,12 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) if (g.NavWindow != window) SetNavWindow(window); - // Assume that SetFocusID() is called in the context where its window->DC.NavLayerCurrent and window->DC.NavFocusScopeIdCurrent are valid. + // Assume that SetFocusID() is called in the context where its window->DC.NavLayerCurrent and g.CurrentFocusScopeId are valid. // Note that window may be != g.CurrentWindow (e.g. SetFocusID call in InputTextEx for multi-line text) const ImGuiNavLayer nav_layer = window->DC.NavLayerCurrent; g.NavId = id; g.NavLayer = nav_layer; - g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent; + g.NavFocusScopeId = g.CurrentFocusScopeId; window->NavLastIds[nav_layer] = id; if (g.LastItemData.ID == id) window->NavRectRel[nav_layer] = WindowRectAbsToRel(window, g.LastItemData.NavRect); @@ -10139,7 +10150,7 @@ static void ImGui::NavApplyItemToResult(ImGuiNavItemData* result) ImGuiWindow* window = g.CurrentWindow; result->Window = window; result->ID = g.LastItemData.ID; - result->FocusScopeId = window->DC.NavFocusScopeIdCurrent; + result->FocusScopeId = g.CurrentFocusScopeId; result->InFlags = g.LastItemData.InFlags; result->RectRel = WindowRectAbsToRel(window, g.LastItemData.NavRect); } @@ -10206,7 +10217,7 @@ static void ImGui::NavProcessItem() if (g.NavWindow != window) SetNavWindow(window); // Always refresh g.NavWindow, because some operations such as FocusItem() may not have a window. g.NavLayer = window->DC.NavLayerCurrent; - g.NavFocusScopeId = window->DC.NavFocusScopeIdCurrent; + g.NavFocusScopeId = g.CurrentFocusScopeId; g.NavIdIsAlive = true; window->NavRectRel[window->DC.NavLayerCurrent] = WindowRectAbsToRel(window, nav_bb); // Store item bounding box (relative to window position) } @@ -10394,7 +10405,8 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit) if (window->Flags & ImGuiWindowFlags_NoNavInputs) { - g.NavId = g.NavFocusScopeId = 0; + g.NavId = 0; + g.NavFocusScopeId = window->NavRootFocusScopeId; return; } @@ -10404,7 +10416,7 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit) IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from NavInitWindow(), init_for_nav=%d, window=\"%s\", layer=%d\n", init_for_nav, window->Name, g.NavLayer); if (init_for_nav) { - SetNavID(0, g.NavLayer, 0, ImRect()); + SetNavID(0, g.NavLayer, window->NavRootFocusScopeId, ImRect()); g.NavInitRequest = true; g.NavInitRequestFromMove = false; g.NavInitResultId = 0; @@ -10414,7 +10426,7 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit) else { g.NavId = window->NavLastIds[0]; - g.NavFocusScopeId = 0; + g.NavFocusScopeId = window->NavRootFocusScopeId; } } @@ -10738,7 +10750,7 @@ void ImGui::NavUpdateCreateMoveRequest() inner_rect_rel.Min.y = clamp_y ? (inner_rect_rel.Min.y + pad_y) : -FLT_MAX; inner_rect_rel.Max.y = clamp_y ? (inner_rect_rel.Max.y - pad_y) : +FLT_MAX; window->NavRectRel[g.NavLayer].ClipWithFull(inner_rect_rel); - g.NavId = g.NavFocusScopeId = 0; + g.NavId = /*g.NavFocusScopeId =*/ 0; } } @@ -10921,7 +10933,7 @@ 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 if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup) || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow))) g.NavWindow->NavLastIds[0] = 0; - g.NavId = g.NavFocusScopeId = 0; + g.NavId = /*g.NavFocusScopeId =*/ 0; } } diff --git a/imgui.h b/imgui.h index 8fa9a65a..5fb6b9b5 100644 --- a/imgui.h +++ b/imgui.h @@ -23,7 +23,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM > 12345') #define IMGUI_VERSION "1.89 WIP" -#define IMGUI_VERSION_NUM 18834 +#define IMGUI_VERSION_NUM 18835 #define IMGUI_HAS_TABLE /* diff --git a/imgui_internal.h b/imgui_internal.h index 9fd0ede2..8aeda428 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1388,6 +1388,14 @@ struct ImGuiNavItemData void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; DistBox = DistCenter = DistAxial = FLT_MAX; } }; +struct ImGuiFocusScope +{ + ImGuiID FocusScopeId; + ImGuiWindow* Window; + + ImGuiFocusScope() { memset(this, 0, sizeof(*this)); } +}; + //----------------------------------------------------------------------------- // [SECTION] Columns support //----------------------------------------------------------------------------- @@ -1688,6 +1696,7 @@ struct ImGuiContext #endif // Next window/item data + ImGuiID CurrentFocusScopeId; // == g.FocusScopeStack.back().FocusScopeId ImGuiItemFlags CurrentItemFlags; // == g.ItemFlagsStack.back() ImGuiNextItemData NextItemData; // Storage for SetNextItem** functions ImGuiLastItemData LastItemData; // Storage for last submitted item (setup by ItemAdd) @@ -1697,12 +1706,13 @@ struct ImGuiContext ImVector ColorStack; // Stack for PushStyleColor()/PopStyleColor() - inherited by Begin() ImVector StyleVarStack; // Stack for PushStyleVar()/PopStyleVar() - inherited by Begin() ImVector FontStack; // Stack for PushFont()/PopFont() - inherited by Begin() - ImVector FocusScopeStack; // Stack for PushFocusScope()/PopFocusScope() - not inherited by Begin(), unless child window + ImVector FocusScopeStack; // Stack for PushFocusScope()/PopFocusScope() - inherited by BeginChild(), pushed into by Begin() ImVectorItemFlagsStack; // Stack for PushItemFlag()/PopItemFlag() - inherited by Begin() ImVectorGroupStack; // Stack for BeginGroup()/EndGroup() - not inherited by Begin() ImVectorOpenPopupStack; // Which popups are open (persistent) ImVectorBeginPopupStack; // Which level of BeginPopup() we are in (reset every frame) int BeginMenuCount; + int FocusScopeStackLocked; // Prevent PushFocusScope()/PopFocusScope() // Viewports ImVector Viewports; // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData. @@ -1937,8 +1947,10 @@ struct ImGuiContext ActiveIdUsingNavInputMask = 0x00; #endif + CurrentFocusScopeId = 0; CurrentItemFlags = ImGuiItemFlags_None; BeginMenuCount = 0; + FocusScopeStackLocked = 0; NavWindow = NULL; NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavActivateInputId = 0; @@ -2068,7 +2080,6 @@ struct IMGUI_API ImGuiWindowTempData ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1) short NavLayersActiveMask; // Which layers have been written to (result from previous frame) short NavLayersActiveMaskNext;// Which layers have been written to (accumulator for current frame) - ImGuiID NavFocusScopeIdCurrent; // Current focus scope ID while appending bool NavHideHighlightOneFrame; bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f) @@ -2186,6 +2197,7 @@ struct IMGUI_API ImGuiWindow ImGuiWindow* NavLastChildNavWindow; // When going to the menu bar, we remember the child window we came from. (This could probably be made implicit if we kept g.Windows sorted by last focused including child window.) ImGuiID NavLastIds[ImGuiNavLayer_COUNT]; // Last known NavId for this window, per layer (0/1) ImRect NavRectRel[ImGuiNavLayer_COUNT]; // Reference rectangle, in window relative space + ImGuiID NavRootFocusScopeId; // Focus Scope ID at the time of Begin() int MemoryDrawListIdxCapacity; // Backup of last idx/vtx count, so when waking up the window we can preallocate and avoid iterative alloc/copy int MemoryDrawListVtxCapacity; @@ -2725,14 +2737,6 @@ namespace ImGui IMGUI_API void SetNavWindow(ImGuiWindow* window); IMGUI_API void SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel); - // Focus Scope (WIP) - // This is generally used to identify a selection set (multiple of which may be in the same window), as selection - // patterns generally need to react (e.g. clear selection) when landing on an item of the set. - IMGUI_API void PushFocusScope(ImGuiID id); - IMGUI_API void PopFocusScope(); - inline ImGuiID GetFocusedFocusScope() { ImGuiContext& g = *GImGui; return g.NavFocusScopeId; } // Focus scope which is actually active - inline ImGuiID GetFocusScope() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.NavFocusScopeIdCurrent; } // Focus scope we are outputting into, set by PushFocusScope() - // Inputs // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions. inline bool IsNamedKey(ImGuiKey key) { return key >= ImGuiKey_NamedKey_BEGIN && key < ImGuiKey_NamedKey_END; } @@ -2767,6 +2771,18 @@ namespace ImGui inline bool IsKeyPressedMap(ImGuiKey key, bool repeat = true) { IM_ASSERT(IsNamedKey(key)); return IsKeyPressed(key, repeat); } // [removed in 1.87] #endif + // [EXPERIMENTAL] Focus Scope + // This is generally used to identify a unique input location (for e.g. a selection set) + // There is one per window (automatically set in Begin), but: + // - Selection patterns generally need to react (e.g. clear a selection) when landing on one item of the set. + // So in order to identify a set multiple lists in same window may each need a focus scope. + // If you imagine an hypothetical BeginSelectionGroup()/EndSelectionGroup() api, it would likely call PushFocusScope()/EndFocusScope() + // - Shortcut routing also use focus scope as a default location identifier if an owner is not provided. + // We don't use the ID Stack for this as it is common to want them separate. + IMGUI_API void PushFocusScope(ImGuiID id); + IMGUI_API void PopFocusScope(); + inline ImGuiID GetCurrentFocusScope() { ImGuiContext& g = *GImGui; return g.CurrentFocusScopeId; } // Focus scope we are outputting into, set by PushFocusScope() + // Drag and Drop IMGUI_API bool IsDragDropActive(); IMGUI_API bool BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 746c6364..cfb6c502 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6329,7 +6329,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl // - (1) it would require focus scope to be set, need exposing PushFocusScope() or equivalent (e.g. BeginSelection() calling PushFocusScope()) // - (2) usage will fail with clipped items // The multi-select API aim to fix those issues, e.g. may be replaced with a BeginSelection() API. - if ((flags & ImGuiSelectableFlags_SelectOnNav) && g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == window->DC.NavFocusScopeIdCurrent) + if ((flags & ImGuiSelectableFlags_SelectOnNav) && g.NavJustMovedToId != 0 && g.NavJustMovedToFocusScopeId == g.CurrentFocusScopeId) if (g.NavJustMovedToId == id) selected = pressed = true; @@ -6338,7 +6338,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl { if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent) { - SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent, WindowRectAbsToRel(window, bb)); // (bb == NavRect) + SetNavID(id, window->DC.NavLayerCurrent, g.CurrentFocusScopeId, WindowRectAbsToRel(window, bb)); // (bb == NavRect) g.NavDisableHighlight = true; } } From 7109f32f963564c633abb7448aa250a5844b2b7c Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 3 Nov 2022 16:25:15 +0100 Subject: [PATCH 12/13] Internals: tidying up and stripping more of focus scope code. --- imgui.cpp | 26 ++++++++------------------ imgui_internal.h | 14 ++------------ 2 files changed, 10 insertions(+), 30 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ded31fa7..d7609dbc 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6329,9 +6329,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->ParentWindowInBeginStack = parent_window_in_stack; } - // Add to focus scope stack - inherited by default by child windows from parent, reset by regular window - //if (window == window->RootWindow && (window->Flags & ImGuiWindowFlags_ChildMenu) == 0) - PushFocusScope(window->ID); + // Add to focus scope stack + PushFocusScope(window->ID); window->NavRootFocusScopeId = g.CurrentFocusScopeId; g.CurrentWindow = NULL; @@ -6942,8 +6941,7 @@ void ImGui::End() if (window->DC.CurrentColumns) EndColumns(); PopClipRect(); // Inner window clip rectangle - //if (window == window->RootWindow && (window->Flags & ImGuiWindowFlags_ChildMenu) == 0) - PopFocusScope(); + PopFocusScope(); // Stop logging if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging @@ -7624,24 +7622,16 @@ void ImGui::ActivateItem(ImGuiID id) void ImGui::PushFocusScope(ImGuiID id) { ImGuiContext& g = *GImGui; - if (g.FocusScopeStackLocked > 0) - return; - ImGuiFocusScope scope; - scope.FocusScopeId = id; - scope.Window = g.CurrentWindow; - g.FocusScopeStack.push_back(scope); - g.CurrentFocusScopeId = scope.FocusScopeId; + g.FocusScopeStack.push_back(id); + g.CurrentFocusScopeId = id; } void ImGui::PopFocusScope() { ImGuiContext& g = *GImGui; - if (g.FocusScopeStackLocked > 0) - return; IM_ASSERT(g.FocusScopeStack.Size > 0); // Too many PopFocusScope() ? - IM_ASSERT(g.FocusScopeStack.back().Window == g.CurrentWindow); // Mismatched pop location? g.FocusScopeStack.pop_back(); - g.CurrentFocusScopeId = g.FocusScopeStack.Size ? g.FocusScopeStack.back().FocusScopeId : 0; + g.CurrentFocusScopeId = g.FocusScopeStack.Size ? g.FocusScopeStack.back() : 0; } // Note: this will likely be called ActivateItem() once we rework our Focus/Activation system! @@ -10750,7 +10740,7 @@ void ImGui::NavUpdateCreateMoveRequest() inner_rect_rel.Min.y = clamp_y ? (inner_rect_rel.Min.y + pad_y) : -FLT_MAX; inner_rect_rel.Max.y = clamp_y ? (inner_rect_rel.Max.y - pad_y) : +FLT_MAX; window->NavRectRel[g.NavLayer].ClipWithFull(inner_rect_rel); - g.NavId = /*g.NavFocusScopeId =*/ 0; + g.NavId = 0; } } @@ -10933,7 +10923,7 @@ 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 if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup) || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow))) g.NavWindow->NavLastIds[0] = 0; - g.NavId = /*g.NavFocusScopeId =*/ 0; + g.NavId = 0; } } diff --git a/imgui_internal.h b/imgui_internal.h index 8aeda428..c5ddac76 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1388,14 +1388,6 @@ struct ImGuiNavItemData void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; DistBox = DistCenter = DistAxial = FLT_MAX; } }; -struct ImGuiFocusScope -{ - ImGuiID FocusScopeId; - ImGuiWindow* Window; - - ImGuiFocusScope() { memset(this, 0, sizeof(*this)); } -}; - //----------------------------------------------------------------------------- // [SECTION] Columns support //----------------------------------------------------------------------------- @@ -1696,7 +1688,7 @@ struct ImGuiContext #endif // Next window/item data - ImGuiID CurrentFocusScopeId; // == g.FocusScopeStack.back().FocusScopeId + ImGuiID CurrentFocusScopeId; // == g.FocusScopeStack.back() ImGuiItemFlags CurrentItemFlags; // == g.ItemFlagsStack.back() ImGuiNextItemData NextItemData; // Storage for SetNextItem** functions ImGuiLastItemData LastItemData; // Storage for last submitted item (setup by ItemAdd) @@ -1706,13 +1698,12 @@ struct ImGuiContext ImVector ColorStack; // Stack for PushStyleColor()/PopStyleColor() - inherited by Begin() ImVector StyleVarStack; // Stack for PushStyleVar()/PopStyleVar() - inherited by Begin() ImVector FontStack; // Stack for PushFont()/PopFont() - inherited by Begin() - ImVector FocusScopeStack; // Stack for PushFocusScope()/PopFocusScope() - inherited by BeginChild(), pushed into by Begin() + ImVector FocusScopeStack; // Stack for PushFocusScope()/PopFocusScope() - inherited by BeginChild(), pushed into by Begin() ImVectorItemFlagsStack; // Stack for PushItemFlag()/PopItemFlag() - inherited by Begin() ImVectorGroupStack; // Stack for BeginGroup()/EndGroup() - not inherited by Begin() ImVectorOpenPopupStack; // Which popups are open (persistent) ImVectorBeginPopupStack; // Which level of BeginPopup() we are in (reset every frame) int BeginMenuCount; - int FocusScopeStackLocked; // Prevent PushFocusScope()/PopFocusScope() // Viewports ImVector Viewports; // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData. @@ -1950,7 +1941,6 @@ struct ImGuiContext CurrentFocusScopeId = 0; CurrentItemFlags = ImGuiItemFlags_None; BeginMenuCount = 0; - FocusScopeStackLocked = 0; NavWindow = NULL; NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavActivateInputId = 0; From 529cba19b09cf6db206de2b9eaa3152ecb2feff8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 24 Oct 2022 22:53:43 +0200 Subject: [PATCH 13/13] Debug Tools: Added DebugLocateItem()/DebugLocateItemOnHover() to visually locate items when hovering a 0xXXXXXXXX value. (#5855, #2673, #4631) --- docs/CHANGELOG.txt | 4 ++- imgui.cpp | 67 +++++++++++++++++++++++++++++++++++++++++----- imgui_internal.h | 7 +++++ imgui_widgets.cpp | 1 + 4 files changed, 72 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ffc98031..e787b2d2 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -175,7 +175,9 @@ Other Changes: - Misc: ImGuiKey is now a typed enum, allowing ImGuiKey_XXX symbols to be named in debuggers. (#4921) - Misc: better error reporting for PopStyleColor()/PopStyleVar() + easier to recover. (#1651) - Misc: io.Framerate moving average now converge in 60 frames instead of 120. (#5236, #4138) -- Debug Tools: Debug Log: Added 'IO' and 'Clipper' events logging. +- Debug Tools: Debug Log: Visually locate items when hovering a 0xXXXXXXXX value. (#5855) +- Debug Tools: Debug Log: Added 'IO' and 'Clipper' events logging. (#5855) +- Debug Tools: Metrics: Visually locate items when hovering a 0xXXXXXXXX value (in most places). - Debug Tools: Item Picker: Mouse button can be changed by holding Ctrl+Shift, making it easier to use the Item Picker in e.g. menus. (#2673) - Docs: Fixed various typos in comments and documentations. (#5649, #5675, #5679) [@tocic, @lessigsx] diff --git a/imgui.cpp b/imgui.cpp index d7609dbc..2ecd365d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4707,6 +4707,8 @@ void ImGui::NewFrame() // [DEBUG] Update debug features UpdateDebugToolItemPicker(); UpdateDebugToolStackQueries(); + if (g.DebugLocateFrames > 0 && --g.DebugLocateFrames == 0) + g.DebugLocateId = 0; // Create implicit/fallback window - which we will only render it if the user has added something to it. // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags. @@ -6854,6 +6856,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // This is useful to allow creating context menus on title bar only, etc. SetLastItemData(window->MoveId, g.CurrentItemFlags, IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0, title_bar_rect); + // [DEBUG] + if (g.DebugLocateId != 0 && (window->ID == g.DebugLocateId || window->MoveId == g.DebugLocateId)) + DebugLocateItemResolveWithLastItem(); + // [Test Engine] Register title bar / tab if (!(window->Flags & ImGuiWindowFlags_NoTitleBar)) IMGUI_TEST_ENGINE_ITEM_ADD(g.LastItemData.Rect, g.LastItemData.ID); @@ -8690,6 +8696,9 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu if (!g.LogEnabled) return false; + // [DEBUG] + if (id != 0 && id == g.DebugLocateId) + DebugLocateItemResolveWithLastItem(); //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them) @@ -12945,6 +12954,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) Text("ITEMS"); Indent(); Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, GetInputSourceName(g.ActiveIdSource)); + DebugLocateItemOnHover(g.ActiveId); Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); int active_id_using_key_input_count = 0; @@ -12954,12 +12964,14 @@ void ImGui::ShowMetricsWindow(bool* p_open) Text("HoveredId: 0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Not displaying g.HoveredId as it is update mid-frame Text("HoverDelayId: 0x%08X, Timer: %.2f, ClearTimer: %.2f", g.HoverDelayId, g.HoverDelayTimer, g.HoverDelayClearTimer); Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize); + DebugLocateItemOnHover(g.DragDropPayload.SourceId); Unindent(); Text("NAV,FOCUS"); Indent(); Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL"); Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer); + DebugLocateItemOnHover(g.NavId); Text("NavInputSource: %s", GetInputSourceName(g.NavInputSource)); Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible); Text("NavActivateId/DownId/PressedId/InputId: %08X/%08X/%08X/%08X", g.NavActivateId, g.NavActivateDownId, g.NavActivatePressedId, g.NavActivateInputId); @@ -13383,13 +13395,10 @@ void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label) { ImRect r = window->NavRectRel[layer]; if (r.Min.x >= r.Max.y && r.Min.y >= r.Max.y) - { BulletText("NavLastIds[%d]: 0x%08X", layer, window->NavLastIds[layer]); - continue; - } - BulletText("NavLastIds[%d]: 0x%08X at +(%.1f,%.1f)(%.1f,%.1f)", layer, window->NavLastIds[layer], r.Min.x, r.Min.y, r.Max.x, r.Max.y); - if (IsItemHovered()) - GetForegroundDrawList(window)->AddRect(r.Min + window->Pos, r.Max + window->Pos, IM_COL32(255, 255, 0, 255)); + else + BulletText("NavLastIds[%d]: 0x%08X at +(%.1f,%.1f)(%.1f,%.1f)", layer, window->NavLastIds[layer], r.Min.x, r.Min.y, r.Max.x, r.Max.y); + DebugLocateItemOnHover(window->NavLastIds[layer]); } BulletText("NavLayersActiveMask: %X, NavLastChildNavWindow: %s", window->DC.NavLayersActiveMask, window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL"); if (window->RootWindow != window) { DebugNodeWindow(window->RootWindow, "RootWindow"); } @@ -13504,6 +13513,20 @@ void ImGui::ShowDebugLogWindow(bool* p_open) const char* line_begin = g.DebugLogIndex.get_line_begin(g.DebugLogBuf.c_str(), line_no); const char* line_end = g.DebugLogIndex.get_line_end(g.DebugLogBuf.c_str(), line_no); TextUnformatted(line_begin, line_end); + ImRect text_rect = g.LastItemData.Rect; + if (IsItemHovered()) + for (const char* p = line_begin; p < line_end - 10; p++) + { + ImGuiID id = 0; + if (p[0] != '0' || (p[1] != 'x' && p[1] != 'X') || sscanf(p + 2, "%X", &id) != 1) + continue; + ImVec2 p0 = CalcTextSize(line_begin, p); + ImVec2 p1 = CalcTextSize(p, p + 10); + g.LastItemData.Rect = ImRect(text_rect.Min + ImVec2(p0.x, 0.0f), text_rect.Min + ImVec2(p0.x + p1.x, p1.y)); + if (IsMouseHoveringRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, true)) + DebugLocateItemOnHover(id); + p += 10; + } } if (GetScrollY() >= GetScrollMaxY()) SetScrollHereY(1.0f); @@ -13516,6 +13539,38 @@ void ImGui::ShowDebugLogWindow(bool* p_open) // [SECTION] OTHER DEBUG TOOLS (ITEM PICKER, STACK TOOL) //----------------------------------------------------------------------------- +static const ImU32 DEBUG_LOCATE_ITEM_COLOR = IM_COL32(0, 255, 0, 255); // Green + +void ImGui::DebugLocateItem(ImGuiID target_id) +{ + ImGuiContext& g = *GImGui; + g.DebugLocateId = target_id; + g.DebugLocateFrames = 2; +} + +void ImGui::DebugLocateItemOnHover(ImGuiID target_id) +{ + if (target_id == 0 || !IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenBlockedByPopup)) + return; + ImGuiContext& g = *GImGui; + DebugLocateItem(target_id); + GetForegroundDrawList(g.CurrentWindow)->AddRect(g.LastItemData.Rect.Min - ImVec2(3.0f, 3.0f), g.LastItemData.Rect.Max + ImVec2(3.0f, 3.0f), DEBUG_LOCATE_ITEM_COLOR); +} + +void ImGui::DebugLocateItemResolveWithLastItem() +{ + ImGuiContext& g = *GImGui; + ImGuiLastItemData item_data = g.LastItemData; + g.DebugLocateId = 0; + ImDrawList* draw_list = GetForegroundDrawList(g.CurrentWindow); + ImRect r = item_data.Rect; + r.Expand(3.0f); + ImVec2 p1 = g.IO.MousePos; + ImVec2 p2 = ImVec2((p1.x < r.Min.x) ? r.Min.x : (p1.x > r.Max.x) ? r.Max.x : p1.x, (p1.y < r.Min.y) ? r.Min.y : (p1.y > r.Max.y) ? r.Max.y : p1.y); + draw_list->AddRect(r.Min, r.Max, DEBUG_LOCATE_ITEM_COLOR); + draw_list->AddLine(p1, p2, DEBUG_LOCATE_ITEM_COLOR); +} + // [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack. void ImGui::UpdateDebugToolItemPicker() { diff --git a/imgui_internal.h b/imgui_internal.h index c5ddac76..ec2c59f1 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1690,6 +1690,7 @@ struct ImGuiContext // Next window/item data ImGuiID CurrentFocusScopeId; // == g.FocusScopeStack.back() ImGuiItemFlags CurrentItemFlags; // == g.ItemFlagsStack.back() + ImGuiID DebugLocateId; // Storage for DebugLocateItemOnHover() feature: this is read by ItemAdd() so we keep it in a hot/cached location ImGuiNextItemData NextItemData; // Storage for SetNextItem** functions ImGuiLastItemData LastItemData; // Storage for last submitted item (setup by ItemAdd) ImGuiNextWindowData NextWindowData; // Storage for SetNextWindow** functions @@ -1867,6 +1868,7 @@ struct ImGuiContext ImGuiDebugLogFlags DebugLogFlags; ImGuiTextBuffer DebugLogBuf; ImGuiTextIndex DebugLogIndex; + ImU8 DebugLocateFrames; // For DebugLocateItemOnHover(). This is used together with DebugLocateId which is in a hot/cached spot above. bool DebugItemPickerActive; // Item picker is active (started with DebugStartItemPicker()) ImU8 DebugItemPickerMouseButton; ImGuiID DebugItemPickerBreakId; // Will call IM_DEBUG_BREAK() when encountering this ID @@ -2029,6 +2031,8 @@ struct ImGuiContext LogDepthToExpand = LogDepthToExpandDefault = 2; DebugLogFlags = ImGuiDebugLogFlags_OutputToTTY; + DebugLocateId = 0; + DebugLocateFrames = 0; DebugItemPickerActive = false; DebugItemPickerMouseButton = ImGuiMouseButton_Left; DebugItemPickerBreakId = 0; @@ -2958,6 +2962,9 @@ namespace ImGui IMGUI_API void ErrorCheckEndFrameRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL); IMGUI_API void ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, void* user_data = NULL); IMGUI_API void ErrorCheckUsingSetCursorPosToExtendParentBoundaries(); + IMGUI_API void DebugLocateItem(ImGuiID target_id); // Call sparingly: only 1 at the same time! + IMGUI_API void DebugLocateItemOnHover(ImGuiID target_id); // Only call on reaction to a mouse Hover: because only 1 at the same time! + IMGUI_API void DebugLocateItemResolveWithLastItem(); inline void DebugDrawItemRect(ImU32 col = IM_COL32(255,0,0,255)) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; GetForegroundDrawList(window)->AddRect(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, col); } inline void DebugStartItemPicker() { ImGuiContext& g = *GImGui; g.DebugItemPickerActive = true; } IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index cfb6c502..be36d305 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4845,6 +4845,7 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state) ImStb::STB_TexteditState* stb_state = &state->Stb; ImStb::StbUndoState* undo_state = &stb_state->undostate; Text("ID: 0x%08X, ActiveID: 0x%08X", state->ID, g.ActiveId); + DebugLocateItemOnHover(state->ID); Text("CurLenW: %d, CurLenA: %d, Cursor: %d, Selection: %d..%d", state->CurLenA, state->CurLenW, stb_state->cursor, stb_state->select_start, stb_state->select_end); Text("undo_point: %d, redo_point: %d, undo_char_point: %d, redo_char_point: %d", undo_state->undo_point, undo_state->redo_point, undo_state->undo_char_point, undo_state->redo_char_point); if (BeginChild("undopoints", ImVec2(0.0f, GetTextLineHeight() * 15), true)) // Visualize undo state