mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-15 01:17:00 +00:00
Menus: Separate menu sets by nav layer. (#3496, #4797) + Demo: Remove incorrect and useless suggestion to use PushID().
Fixes a common case where opening menu in one nav layer and hovering a menu in another nav layer would open that menu without a click.
This commit is contained in:
parent
a35e876978
commit
0b1bcfcc20
@ -101,6 +101,8 @@ Other Changes:
|
|||||||
- Menus: Adjusted BeginMenu() closing logic so hovering void or non-MenuItem() in parent window
|
- Menus: Adjusted BeginMenu() closing logic so hovering void or non-MenuItem() in parent window
|
||||||
always lead to menu closure. Fixes using items that are not MenuItem() or BeginItem() at the root
|
always lead to menu closure. Fixes using items that are not MenuItem() or BeginItem() at the root
|
||||||
level of a popup with a child menu opened.
|
level of a popup with a child menu opened.
|
||||||
|
- Menus: Menus emitted from the main/scrolling layer are not part of the same menuset as menus emitted
|
||||||
|
from the menu-bar, avoiding accidental hovering from one to the other. (#3496, #4797) [@rokups]
|
||||||
- Stack Tool: Added option to copy item path to clipboard. (#4631)
|
- Stack Tool: Added option to copy item path to clipboard. (#4631)
|
||||||
- Settings: Fixed out-of-bounds read when .ini file on disk is empty. (#5351) [@quantum5]
|
- Settings: Fixed out-of-bounds read when .ini file on disk is empty. (#5351) [@quantum5]
|
||||||
- DrawList: Fixed PathArcTo() emitting terminating vertices too close to arc vertices. (#4993) [@thedmd]
|
- DrawList: Fixed PathArcTo() emitting terminating vertices too close to arc vertices. (#4993) [@thedmd]
|
||||||
|
@ -6071,6 +6071,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|||||||
{
|
{
|
||||||
ImGuiPopupData& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size];
|
ImGuiPopupData& popup_ref = g.OpenPopupStack[g.BeginPopupStack.Size];
|
||||||
popup_ref.Window = window;
|
popup_ref.Window = window;
|
||||||
|
popup_ref.ParentNavLayer = parent_window_in_stack->DC.NavLayerCurrent;
|
||||||
g.BeginPopupStack.push_back(popup_ref);
|
g.BeginPopupStack.push_back(popup_ref);
|
||||||
window->PopupId = popup_ref.PopupId;
|
window->PopupId = popup_ref.PopupId;
|
||||||
}
|
}
|
||||||
|
@ -3546,19 +3546,12 @@ static void ShowDemoWindowPopups()
|
|||||||
ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
|
ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
// Note: As a quirk in this very specific example, we want to differentiate the parent of this menu from the
|
|
||||||
// parent of the various popup menus above. To do so we are encloding the items in a PushID()/PopID() block
|
|
||||||
// to make them two different menusets. If we don't, opening any popup above and hovering our menu here would
|
|
||||||
// open it. This is because once a menu is active, we allow to switch to a sibling menu by just hovering on it,
|
|
||||||
// which is the desired behavior for regular menus.
|
|
||||||
ImGui::PushID("foo");
|
|
||||||
ImGui::MenuItem("Menu item", "CTRL+M");
|
ImGui::MenuItem("Menu item", "CTRL+M");
|
||||||
if (ImGui::BeginMenu("Menu inside a regular window"))
|
if (ImGui::BeginMenu("Menu inside a regular window"))
|
||||||
{
|
{
|
||||||
ShowExampleMenuFile();
|
ShowExampleMenuFile();
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
ImGui::PopID();
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
|
@ -1038,12 +1038,13 @@ struct ImGuiPopupData
|
|||||||
ImGuiID PopupId; // Set on OpenPopup()
|
ImGuiID PopupId; // Set on OpenPopup()
|
||||||
ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup()
|
ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup()
|
||||||
ImGuiWindow* SourceWindow; // Set on OpenPopup() copy of NavWindow at the time of opening the popup
|
ImGuiWindow* SourceWindow; // Set on OpenPopup() copy of NavWindow at the time of opening the popup
|
||||||
|
int ParentNavLayer; // Resolved on BeginPopup(). Actually a ImGuiNavLayer type (declared down below), initialized to -1 which is not part of an enum, but serves well-enough as "not any of layers" value
|
||||||
int OpenFrameCount; // Set on OpenPopup()
|
int OpenFrameCount; // Set on OpenPopup()
|
||||||
ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items)
|
ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items)
|
||||||
ImVec2 OpenPopupPos; // Set on OpenPopup(), preferred popup position (typically == OpenMousePos when using mouse)
|
ImVec2 OpenPopupPos; // Set on OpenPopup(), preferred popup position (typically == OpenMousePos when using mouse)
|
||||||
ImVec2 OpenMousePos; // Set on OpenPopup(), copy of mouse position at the time of opening popup
|
ImVec2 OpenMousePos; // Set on OpenPopup(), copy of mouse position at the time of opening popup
|
||||||
|
|
||||||
ImGuiPopupData() { memset(this, 0, sizeof(*this)); OpenFrameCount = -1; }
|
ImGuiPopupData() { memset(this, 0, sizeof(*this)); ParentNavLayer = OpenFrameCount = -1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ImGuiNextWindowDataFlags_
|
enum ImGuiNextWindowDataFlags_
|
||||||
|
@ -6939,14 +6939,19 @@ static bool IsRootOfOpenMenuSet()
|
|||||||
if ((g.OpenPopupStack.Size <= g.BeginPopupStack.Size) || (window->Flags & ImGuiWindowFlags_ChildMenu))
|
if ((g.OpenPopupStack.Size <= g.BeginPopupStack.Size) || (window->Flags & ImGuiWindowFlags_ChildMenu))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Initially we used 'OpenParentId' to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items) based on parent ID.
|
// Initially we used 'upper_popup->OpenParentId == window->IDStack.back()' to differentiate multiple menu sets from each others
|
||||||
|
// (e.g. inside menu bar vs loose menu items) based on parent ID.
|
||||||
// This would however prevent the use of e.g. PuhsID() user code submitting menus.
|
// This would however prevent the use of e.g. PuhsID() user code submitting menus.
|
||||||
// Previously this worked between popup and a first child menu because the first child menu always had the _ChildWindow flag,
|
// Previously this worked between popup and a first child menu because the first child menu always had the _ChildWindow flag,
|
||||||
// making hovering on parent popup possible while first child menu was focused - but this was generally a bug with other side effects.
|
// making hovering on parent popup possible while first child menu was focused - but this was generally a bug with other side effects.
|
||||||
// Instead we don't treat Popup specifically (in order to consistently support menu features in them), maybe the first child menu of a Popup
|
// Instead we don't treat Popup specifically (in order to consistently support menu features in them), maybe the first child menu of a Popup
|
||||||
// doesn't have the _ChildWindow flag, and we rely on this IsRootOfOpenMenuSet() check to allow hovering between root window/popup and first chilld menu.
|
// doesn't have the _ChildWindow flag, and we rely on this IsRootOfOpenMenuSet() check to allow hovering between root window/popup and first child menu.
|
||||||
|
// In the end, lack of ID check made it so we could no longer differentiate between separate menu sets. To compensate for that, we at least check parent window nav layer.
|
||||||
|
// This fixes the most common case of menu opening on hover when moving between window content and menu bar. Multiple different menu sets in same nav layer would still
|
||||||
|
// open on hover, but that should be a lesser problem, because if such menus are close in proximity in window content then it won't feel weird and if they are far apart
|
||||||
|
// it likely won't be a problem anyone runs into.
|
||||||
const ImGuiPopupData* upper_popup = &g.OpenPopupStack[g.BeginPopupStack.Size];
|
const ImGuiPopupData* upper_popup = &g.OpenPopupStack[g.BeginPopupStack.Size];
|
||||||
return (/*upper_popup->OpenParentId == window->IDStack.back() &&*/ upper_popup->Window && (upper_popup->Window->Flags & ImGuiWindowFlags_ChildMenu));
|
return (window->DC.NavLayerCurrent == upper_popup->ParentNavLayer && upper_popup->Window && (upper_popup->Window->Flags & ImGuiWindowFlags_ChildMenu));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||||
|
Loading…
Reference in New Issue
Block a user