From 321b84f01fbf3f64db6dbb53deb707d150ce30dc Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 8 Sep 2021 15:05:27 +0200 Subject: [PATCH 1/4] Internals: refactored IsWindowHovered()/IsWindowFocused() to make their logic more similar + change underlying value of ImGuiHoveredFlags_AllowWhenBlockedByPopup + comment out docking only flags. --- imgui.cpp | 66 +++++++++++++++++++++++++------------------------------ imgui.h | 10 +++++---- 2 files changed, 36 insertions(+), 40 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0cb5d7d8..bb051e8b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6740,37 +6740,31 @@ bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags) { IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0); // Flags not supported by this function ImGuiContext& g = *GImGui; - if (g.HoveredWindow == NULL) + ImGuiWindow* ref_window = g.HoveredWindow; + ImGuiWindow* cur_window = g.CurrentWindow; + if (ref_window == NULL) return false; if ((flags & ImGuiHoveredFlags_AnyWindow) == 0) { - ImGuiWindow* window = g.CurrentWindow; - switch (flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) - { - case ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows: - if (g.HoveredWindow->RootWindow != window->RootWindow) - return false; - break; - case ImGuiHoveredFlags_RootWindow: - if (g.HoveredWindow != window->RootWindow) - return false; - break; - case ImGuiHoveredFlags_ChildWindows: - if (!IsWindowChildOf(g.HoveredWindow, window)) - return false; - break; - default: - if (g.HoveredWindow != window) - return false; - break; - } + IM_ASSERT(cur_window); // Not inside a Begin()/End() + + if (flags & ImGuiHoveredFlags_RootWindow) + cur_window = cur_window->RootWindow; + + bool result; + if (flags & ImGuiHoveredFlags_ChildWindows) + result = IsWindowChildOf(ref_window, cur_window); + else + result = (ref_window == cur_window); + if (!result) + return false; } - if (!IsWindowContentHoverable(g.HoveredWindow, flags)) + if (!IsWindowContentHoverable(ref_window, flags)) return false; if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) - if (g.ActiveId != 0 && !g.ActiveIdAllowOverlap && g.ActiveId != g.HoveredWindow->MoveId) + if (g.ActiveId != 0 && !g.ActiveIdAllowOverlap && g.ActiveId != ref_window->MoveId) return false; return true; } @@ -6778,22 +6772,22 @@ bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags) bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags) { ImGuiContext& g = *GImGui; + ImGuiWindow* ref_window = g.NavWindow; + ImGuiWindow* cur_window = g.CurrentWindow; + if (ref_window == NULL) + return false; if (flags & ImGuiFocusedFlags_AnyWindow) - return g.NavWindow != NULL; + return true; + IM_ASSERT(cur_window); // Not inside a Begin()/End() - IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() - switch (flags & (ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows)) - { - case ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows: - return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow; - case ImGuiFocusedFlags_RootWindow: - return g.NavWindow == g.CurrentWindow->RootWindow; - case ImGuiFocusedFlags_ChildWindows: - return g.NavWindow && IsWindowChildOf(g.NavWindow, g.CurrentWindow); - default: - return g.NavWindow == g.CurrentWindow; - } + if (flags & ImGuiHoveredFlags_RootWindow) + cur_window = cur_window->RootWindow; + + if (flags & ImGuiHoveredFlags_ChildWindows) + return IsWindowChildOf(ref_window, cur_window); + else + return (ref_window == cur_window); } // Can we focus this window with CTRL+TAB (or PadMenu + PadFocusPrev/PadFocusNext) diff --git a/imgui.h b/imgui.h index 2fcdbf89..9c4cb933 100644 --- a/imgui.h +++ b/imgui.h @@ -1264,9 +1264,10 @@ enum ImGuiTableBgTarget_ enum ImGuiFocusedFlags_ { ImGuiFocusedFlags_None = 0, - ImGuiFocusedFlags_ChildWindows = 1 << 0, // IsWindowFocused(): Return true if any children of the window is focused - ImGuiFocusedFlags_RootWindow = 1 << 1, // IsWindowFocused(): Test from root window (top most parent of the current hierarchy) - ImGuiFocusedFlags_AnyWindow = 1 << 2, // IsWindowFocused(): Return true if any window is focused. Important: If you are trying to tell how to dispatch your low-level inputs, do NOT use this. Use 'io.WantCaptureMouse' instead! Please read the FAQ! + ImGuiFocusedFlags_ChildWindows = 1 << 0, // Return true if any children of the window is focused + ImGuiFocusedFlags_RootWindow = 1 << 1, // Test from root window (top most parent of the current hierarchy) + ImGuiFocusedFlags_AnyWindow = 1 << 2, // Return true if any window is focused. Important: If you are trying to tell how to dispatch your low-level inputs, do NOT use this. Use 'io.WantCaptureMouse' instead! Please read the FAQ! + //ImGuiFocusedFlags_DockHierarchy = 1 << 3, // Consider docking hierarchy (treat dockspace host as parent of docked window) ImGuiFocusedFlags_RootAndChildWindows = ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows }; @@ -1279,7 +1280,8 @@ enum ImGuiHoveredFlags_ ImGuiHoveredFlags_ChildWindows = 1 << 0, // IsWindowHovered() only: Return true if any children of the window is hovered ImGuiHoveredFlags_RootWindow = 1 << 1, // IsWindowHovered() only: Test from root window (top most parent of the current hierarchy) ImGuiHoveredFlags_AnyWindow = 1 << 2, // IsWindowHovered() only: Return true if any window is hovered - ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 3, // Return true even if a popup window is normally blocking access to this item/window + //ImGuiHoveredFlags_DockHierarchy = 1 << 3, // IsWindowHovered() only: Consider docking hierarchy (treat dockspace host as parent of docked window) + ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 4, // Return true even if a popup window is normally blocking access to this item/window //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 4, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 5, // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns. ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 6, // Return true even if the position is obstructed or overlapped by another window From 17a7084b57f9713ec6538881079d6c5a1b6b3598 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 10 Sep 2021 15:37:59 +0200 Subject: [PATCH 2/4] Menus: Fixed crash when navigating left inside a child window inside a sub-menu. (#4510). --- docs/CHANGELOG.txt | 3 ++- imgui.h | 2 +- imgui_widgets.cpp | 11 ++++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6cf3d6aa..248483ea 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -51,7 +51,8 @@ Other Changes: to common idioms (e.g. passing .data(), .data() + .size() from a null string). (#3615) - Nav: Fixed toggling menu layer with Alt or exiting menu layer with Esc not moving mouse when the NavEnableSetMousePos config flag is set. -- Menus: adjust closing logic to accomodate for varying font size and dpi. +- Menus: Adjust closing logic to accomodate for varying font size and dpi. +- Menus: Fixed crash when navigating left inside a child window inside a sub-menu. (#4510). - Drag and Drop: Fixed using BeginDragDropSource() inside a BeginChild() that returned false. (#4515) - PlotHistogram: Fixed zero-line position when manually specifying min<0 and max>0. (#4349) [@filippocrocchini] - IO: Added 'io.WantCaptureMouseUnlessPopupClose' alternative to `io.WantCaptureMouse'. (#4480) diff --git a/imgui.h b/imgui.h index 9c4cb933..f36c44b0 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 18412 +#define IMGUI_VERSION_NUM 18413 #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 6e6d679d..ddb50b67 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6968,11 +6968,12 @@ void ImGui::EndMenu() // However, it means that with the current code, a BeginMenu() from outside another menu or a menu-bar won't be closable with the Left direction. ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - if (g.NavWindow && g.NavWindow->ParentWindow == window && g.NavMoveDir == ImGuiDir_Left && NavMoveRequestButNoResultYet() && window->DC.LayoutType == ImGuiLayoutType_Vertical) - { - ClosePopupToLevel(g.BeginPopupStack.Size, true); - NavMoveRequestCancel(); - } + if (g.NavMoveDir == ImGuiDir_Left && NavMoveRequestButNoResultYet() && window->DC.LayoutType == ImGuiLayoutType_Vertical) + if (g.NavWindow && (g.NavWindow->RootWindowForNav->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->RootWindowForNav->ParentWindow == window) + { + ClosePopupToLevel(g.BeginPopupStack.Size, true); + NavMoveRequestCancel(); + } EndPopup(); } From 82754561e23f824ec2e88287c00255d049e0d51a Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 13 Sep 2021 15:17:54 +0200 Subject: [PATCH 3/4] Nav: Fixed a few widgets from not setting reference keyboard/gamepad navigation ID when activated with mouse. --- docs/CHANGELOG.txt | 5 +++++ imgui.h | 2 +- imgui_tables.cpp | 2 +- imgui_widgets.cpp | 4 ++++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 248483ea..37f6e455 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -51,6 +51,11 @@ Other Changes: to common idioms (e.g. passing .data(), .data() + .size() from a null string). (#3615) - Nav: Fixed toggling menu layer with Alt or exiting menu layer with Esc not moving mouse when the NavEnableSetMousePos config flag is set. +- Nav: Fixed a few widgets from not setting reference keyboard/gamepad navigation ID when + activated with mouse. More specifically: BeginTabItem(), the scrolling arrows of BeginTabBar(), + the arrow section of TreeNode(), the +/- buttons of InputInt()/InputFloat(), Selectable() with + ImGuiSelectableFlags_SelectOnRelease. More generally: any direct use of ButtonBehavior() with + the PressedOnClick/PressedOnDoubleClick/PressedOnRelease button policy. - Menus: Adjust closing logic to accomodate for varying font size and dpi. - Menus: Fixed crash when navigating left inside a child window inside a sub-menu. (#4510). - Drag and Drop: Fixed using BeginDragDropSource() inside a BeginChild() that returned false. (#4515) diff --git a/imgui.h b/imgui.h index f36c44b0..6ea22bbb 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 18413 +#define IMGUI_VERSION_NUM 18414 #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_tables.cpp b/imgui_tables.cpp index b60676a6..7b783e3c 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1170,7 +1170,7 @@ void ImGui::TableUpdateBorders(ImGuiTable* table) KeepAliveID(column_id); bool hovered = false, held = false; - bool pressed = ButtonBehavior(hit_rect, column_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick); + bool pressed = ButtonBehavior(hit_rect, column_id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnDoubleClick | ImGuiButtonFlags_NoNavFocus); if (pressed && IsMouseDoubleClicked(0)) { TableSetColumnWidthAutoSingle(table, column_n); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index ddb50b67..f8aea16d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -571,6 +571,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool ClearActiveID(); else SetActiveID(id, window); // Hold on ID + if (!(flags & ImGuiButtonFlags_NoNavFocus)) + SetFocusID(id, window); g.ActiveIdMouseButton = mouse_button_clicked; FocusWindow(window); } @@ -581,6 +583,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool const bool has_repeated_at_least_once = (flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[mouse_button_released] >= g.IO.KeyRepeatDelay; if (!has_repeated_at_least_once) pressed = true; + if (!(flags & ImGuiButtonFlags_NoNavFocus)) + SetFocusID(id, window); ClearActiveID(); } From 7b8bc864e9af6c6c9a22125d65595d526ba674c5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 14 Sep 2021 11:09:39 +0200 Subject: [PATCH 4/4] Menus: Fixed vertical alignments of MenuItem() calls within a menu bar. (broken by f8fae022). (#4538) --- docs/CHANGELOG.txt | 1 + imgui_demo.cpp | 1 + imgui_widgets.cpp | 5 +++-- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 37f6e455..2322101f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -56,6 +56,7 @@ Other Changes: the arrow section of TreeNode(), the +/- buttons of InputInt()/InputFloat(), Selectable() with ImGuiSelectableFlags_SelectOnRelease. More generally: any direct use of ButtonBehavior() with the PressedOnClick/PressedOnDoubleClick/PressedOnRelease button policy. +- Menus: Fixed vertical alignments of MenuItem() calls within a menu bar. (broken in 1.84). (#4538) - Menus: Adjust closing logic to accomodate for varying font size and dpi. - Menus: Fixed crash when navigating left inside a child window inside a sub-menu. (#4510). - Drag and Drop: Fixed using BeginDragDropSource() inside a BeginChild() that returned false. (#4515) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 2a16e3c6..3cc50a8f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -379,6 +379,7 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::MenuItem("Documents", NULL, &show_app_documents); ImGui::EndMenu(); } + //if (ImGui::MenuItem("MenuItem")) {} // You can also use MenuItem() inside a menu bar! if (ImGui::BeginMenu("Tools")) { ImGui::MenuItem("Metrics/Debugger", NULL, &show_app_metrics); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index f8aea16d..b055e1ae 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6851,7 +6851,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) } else { - // Menu inside a menu + // Menu inside a regular/vertical menu // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f. // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system. popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y); @@ -7007,10 +7007,11 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut // Note that in this situation: we don't render the shortcut, we render a highlight instead of the selected tick mark. float w = label_size.x; window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f); + ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); pressed = Selectable("", selected, flags, ImVec2(w, 0.0f)); PopStyleVar(); - RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label); + RenderText(text_pos, label); window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). } else