OpenPopup(): Added ImGuiPopupFlags_NoReopen. Nav, Menus: Fixed click on a BeginMenu() followed by right-arrow. (#1497, #1533)

reopen
This commit is contained in:
ocornut 2024-02-08 15:02:22 +01:00
parent f104967c68
commit a06dd7a27b
4 changed files with 38 additions and 13 deletions

View File

@ -56,6 +56,13 @@ Other changes:
- Nav: Fixed pressing Escape while in a child window with _NavFlattened flag. (#7237) - Nav: Fixed pressing Escape while in a child window with _NavFlattened flag. (#7237)
- Nav: Improve handling of Alt key to toggle menu so that key ownership may be claimed on - Nav: Improve handling of Alt key to toggle menu so that key ownership may be claimed on
indiviudal left/right alt key without intefering with the other. indiviudal left/right alt key without intefering with the other.
- Nav, Menus: Fixed click on a BeginMenu() followed by right-arrow from making the child menu
reopen and flicker (using ImGuiPopupFlags_NoReopen).
- OpenPopup(): Added ImGuiPopupFlags_NoReopen flag to specifically not close nd reopen a popup
when it is already open. (#1497, #1533)
(Note that this differs from specific handling we already have in place for the case of calling
OpenPopup() repeatedly every frame: we already didn't reopen in that specific situation, otherwise
the effect would be very disastrous in term of confusion, as reopening would steal focus).
- Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect. - Debug Tools: Metrics: Fixed debug break in SetShortcutRouting() not handling ImGuiMod_Shortcut redirect.
- Debug Tools: Debug Log: Added "Input Routing" logging. - Debug Tools: Debug Log: Added "Input Routing" logging.
- Debug Tools: Added "nop" to IM_DEBUG_BREAK macro on GCC to work around GDB bug (#7266) [@Peter0x44] - Debug Tools: Added "nop" to IM_DEBUG_BREAK macro on GCC to work around GDB bug (#7266) [@Peter0x44]

View File

@ -10773,16 +10773,22 @@ void ImGui::OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags)
} }
else else
{ {
// Gently handle the user mistakenly calling OpenPopup() every frame. It is a programming mistake! However, if we were to run the regular code path, the ui // Gently handle the user mistakenly calling OpenPopup() every frames: it is likely a programming mistake!
// would become completely unusable because the popup will always be in hidden-while-calculating-size state _while_ claiming focus. Which would be a very confusing // However, if we were to run the regular code path, the ui would become completely unusable because the popup will always be
// situation for the programmer. Instead, we silently allow the popup to proceed, it will keep reappearing and the programming error will be more obvious to understand. // in hidden-while-calculating-size state _while_ claiming focus. Which is extremely confusing situation for the programmer.
if (g.OpenPopupStack[current_stack_size].PopupId == id && g.OpenPopupStack[current_stack_size].OpenFrameCount == g.FrameCount - 1) // Instead, for successive frames calls to OpenPopup(), we silently avoid reopening even if ImGuiPopupFlags_NoReopen is not specified.
bool keep_existing = false;
if (g.OpenPopupStack[current_stack_size].PopupId == id)
if ((g.OpenPopupStack[current_stack_size].OpenFrameCount == g.FrameCount - 1) || (popup_flags & ImGuiPopupFlags_NoReopen))
keep_existing = true;
if (keep_existing)
{ {
// No reopen
g.OpenPopupStack[current_stack_size].OpenFrameCount = popup_ref.OpenFrameCount; g.OpenPopupStack[current_stack_size].OpenFrameCount = popup_ref.OpenFrameCount;
} }
else else
{ {
// Close child popups if any, then flag popup for open/reopen // Reopen: close child popups if any, then flag popup for open/reopen (set position, focus, init navigation)
ClosePopupToLevel(current_stack_size, false); ClosePopupToLevel(current_stack_size, false);
g.OpenPopupStack.push_back(popup_ref); g.OpenPopupStack.push_back(popup_ref);
} }

12
imgui.h
View File

@ -24,7 +24,7 @@
// Library Version // Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.90.2 WIP" #define IMGUI_VERSION "1.90.2 WIP"
#define IMGUI_VERSION_NUM 19017 #define IMGUI_VERSION_NUM 19018
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
/* /*
@ -1122,10 +1122,12 @@ enum ImGuiPopupFlags_
ImGuiPopupFlags_MouseButtonMiddle = 2, // For BeginPopupContext*(): open on Middle Mouse release. Guaranteed to always be == 2 (same as ImGuiMouseButton_Middle) ImGuiPopupFlags_MouseButtonMiddle = 2, // For BeginPopupContext*(): open on Middle Mouse release. Guaranteed to always be == 2 (same as ImGuiMouseButton_Middle)
ImGuiPopupFlags_MouseButtonMask_ = 0x1F, ImGuiPopupFlags_MouseButtonMask_ = 0x1F,
ImGuiPopupFlags_MouseButtonDefault_ = 1, ImGuiPopupFlags_MouseButtonDefault_ = 1,
ImGuiPopupFlags_NoOpenOverExistingPopup = 1 << 5, // For OpenPopup*(), BeginPopupContext*(): don't open if there's already a popup at the same level of the popup stack ImGuiPopupFlags_NoReopen = 1 << 5, // For OpenPopup*(), BeginPopupContext*(): don't reopen same popup if already open (won't reposition, won't reinitialize navigation)
ImGuiPopupFlags_NoOpenOverItems = 1 << 6, // For BeginPopupContextWindow(): don't return true when hovering items, only when hovering empty space //ImGuiPopupFlags_NoReopenAlwaysNavInit = 1 << 6, // For OpenPopup*(), BeginPopupContext*(): focus and initialize navigation even when not reopening.
ImGuiPopupFlags_AnyPopupId = 1 << 7, // For IsPopupOpen(): ignore the ImGuiID parameter and test for any popup. ImGuiPopupFlags_NoOpenOverExistingPopup = 1 << 7, // For OpenPopup*(), BeginPopupContext*(): don't open if there's already a popup at the same level of the popup stack
ImGuiPopupFlags_AnyPopupLevel = 1 << 8, // For IsPopupOpen(): search/test at any level of the popup stack (default test in the current level) ImGuiPopupFlags_NoOpenOverItems = 1 << 8, // For BeginPopupContextWindow(): don't return true when hovering items, only when hovering empty space
ImGuiPopupFlags_AnyPopupId = 1 << 10, // For IsPopupOpen(): ignore the ImGuiID parameter and test for any popup.
ImGuiPopupFlags_AnyPopupLevel = 1 << 11, // For IsPopupOpen(): search/test at any level of the popup stack (default test in the current level)
ImGuiPopupFlags_AnyPopup = ImGuiPopupFlags_AnyPopupId | ImGuiPopupFlags_AnyPopupLevel, ImGuiPopupFlags_AnyPopup = ImGuiPopupFlags_AnyPopupId | ImGuiPopupFlags_AnyPopupLevel,
}; };

View File

@ -7518,6 +7518,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
PopItemFlag(); PopItemFlag();
bool want_open = false; bool want_open = false;
bool want_open_nav_init = false;
bool want_close = false; bool want_close = false;
if (window->DC.LayoutType == ImGuiLayoutType_Vertical) // (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) if (window->DC.LayoutType == ImGuiLayoutType_Vertical) // (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu))
{ {
@ -7560,8 +7561,9 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
want_open = true; want_open = true;
if (g.NavId == id && g.NavMoveDir == ImGuiDir_Right) // Nav-Right to open if (g.NavId == id && g.NavMoveDir == ImGuiDir_Right) // Nav-Right to open
{ {
want_open = true; want_open = want_open_nav_init = true;
NavMoveRequestCancel(); NavMoveRequestCancel();
NavRestoreHighlightAfterMove();
} }
} }
else else
@ -7593,13 +7595,13 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
if (want_open && !menu_is_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size) if (want_open && !menu_is_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size)
{ {
// Don't reopen/recycle same menu level in the same frame, first close the other menu and yield for a frame. // Don't reopen/recycle same menu level in the same frame if it is a different menu ID, first close the other menu and yield for a frame.
OpenPopup(label); OpenPopup(label);
} }
else if (want_open) else if (want_open)
{ {
menu_is_open = true; menu_is_open = true;
OpenPopup(label); OpenPopup(label, ImGuiPopupFlags_NoReopen);// | (want_open_nav_init ? ImGuiPopupFlags_NoReopenAlwaysNavInit : 0));
} }
if (menu_is_open) if (menu_is_open)
@ -7611,6 +7613,14 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
PopStyleVar(); PopStyleVar();
if (menu_is_open) if (menu_is_open)
{ {
// Implement what ImGuiPopupFlags_NoReopenAlwaysNavInit would do:
// Perform an init request in the case the popup was already open (via a previous mouse hover)
if (want_open && want_open_nav_init && !g.NavInitRequest)
{
FocusWindow(g.CurrentWindow, ImGuiFocusRequestFlags_UnlessBelowModal);
NavInitWindow(g.CurrentWindow, false);
}
// Restore LastItemData so IsItemXXXX functions can work after BeginMenu()/EndMenu() // Restore LastItemData so IsItemXXXX functions can work after BeginMenu()/EndMenu()
// (This fixes using IsItemClicked() and IsItemHovered(), but IsItemHovered() also relies on its support for ImGuiItemFlags_NoWindowHoverableCheck) // (This fixes using IsItemClicked() and IsItemHovered(), but IsItemHovered() also relies on its support for ImGuiItemFlags_NoWindowHoverableCheck)
g.LastItemData = last_item_in_parent; g.LastItemData = last_item_in_parent;