Nav: allow ImGuiKey_Menu or Shift + F10 to open context menus. Rework with polling in NavUpdate(). (#8803, #9270)

This might be a little less flexible but removes burden from the higher-frequency calls.
diff --git a/imgui.cpp b/imgui.cpp
index 422cd22..5e4c160 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1358,6 +1358,7 @@
 static void             NavUpdateWindowingApplyFocus(ImGuiWindow* window);
 static void             NavUpdateWindowingOverlay();
 static void             NavUpdateCancelRequest();
+static void             NavUpdateContextMenuRequest();
 static void             NavUpdateCreateMoveRequest();
 static void             NavUpdateCreateTabbingRequest();
 static float            NavUpdatePageUpPageDown();
@@ -4215,6 +4216,7 @@
     NavWindow = NULL;
     NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
     NavLayer = ImGuiNavLayer_Main;
+    NavOpenContextMenuItemId = NavOpenContextMenuWindowId = 0;
     NavNextActivateId = 0;
     NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
     NavHighlightActivatedId = 0;
@@ -12505,38 +12507,21 @@
     ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
     if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
         return true;
-
-    if (g.NavId == id && g.NavId != 0) // == IsItemFocused()
-        if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard)
-           if (Shortcut(ImGuiKey_F10 | ImGuiMod_Shift) || IsKeyReleased(ImGuiKey_Menu, ImGuiKeyOwner_NoOwner))
-           {
-               g.NavInputSource = ImGuiInputSource_Keyboard;
-               SetNavCursorVisibleAfterMove();
-               return true;
-           }
-
+    if (g.NavOpenContextMenuItemId == id && IsItemFocused())
+        return true;
     return false;
 }
 
-bool ImGui::IsPopupOpenRequestForWindow(ImGuiPopupFlags popup_flags, ImGuiID id)
+bool ImGui::IsPopupOpenRequestForWindow(ImGuiPopupFlags popup_flags)
 {
     ImGuiContext& g = *GImGui;
     ImGuiMouseButton mouse_button = GetMouseButtonFromPopupFlags(popup_flags);
     if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
         if (!(popup_flags & ImGuiPopupFlags_NoOpenOverItems) || !IsAnyItemHovered())
             return true;
-
-    // FIXME-NAV: How to meaningful support ImGuiPopupFlags_NoOpenOverItems with keyboard?
-    if (g.CurrentWindow->ID == id && g.NavWindow != NULL)
-        if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard)
-            if (IsWindowChildOf(g.NavWindow, g.CurrentWindow, false))
-                if (Shortcut(ImGuiKey_F10 | ImGuiMod_Shift) || IsKeyReleased(ImGuiKey_Menu, ImGuiKeyOwner_NoOwner))
-                {
-                    g.NavInputSource = ImGuiInputSource_Keyboard;
-                    SetNavCursorVisibleAfterMove();
-                    return true;
-                }
-
+    if (g.NavOpenContextMenuWindowId && g.CurrentWindow->ID)
+        if (IsWindowChildOf(g.NavWindow, g.CurrentWindow, false)) // This enable ordering to be used to disambiguate item vs window (#8803)
+            return true;
     return false;
 }
 
@@ -12590,7 +12575,7 @@
     if (!str_id)
         str_id = "window_context";
     ImGuiID id = window->GetID(str_id);
-    if (IsPopupOpenRequestForWindow(popup_flags, window->ID))
+    if (IsPopupOpenRequestForWindow(popup_flags))
         OpenPopupEx(id, popup_flags);
     return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings);
 }
@@ -13768,6 +13753,7 @@
 
     // Process NavCancel input (to close a popup, get back to parent, clear focus)
     NavUpdateCancelRequest();
+    NavUpdateContextMenuRequest();
 
     // Process manual activation request
     g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = 0;
@@ -14252,6 +14238,23 @@
     }
 }
 
+static void ImGui::NavUpdateContextMenuRequest()
+{
+    ImGuiContext& g = *GImGui;
+    g.NavOpenContextMenuItemId = g.NavOpenContextMenuWindowId = 0;
+    const bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0;
+    if (!nav_keyboard_active || g.NavWindow == NULL)
+        return;
+
+    const bool request = IsKeyReleased(ImGuiKey_Menu, ImGuiKeyOwner_NoOwner) || (IsKeyPressed(ImGuiKey_F10, ImGuiInputFlags_None, ImGuiKeyOwner_NoOwner) && g.IO.KeyMods == ImGuiMod_Shift);
+    if (!request)
+        return;
+    g.NavOpenContextMenuItemId = g.NavId;
+    g.NavOpenContextMenuWindowId = g.NavWindow->ID;
+    g.NavInputSource = ImGuiInputSource_Keyboard;
+    SetNavCursorVisibleAfterMove();
+}
+
 // Handle PageUp/PageDown/Home/End keys
 // Called from NavUpdateCreateMoveRequest() which will use our output to create a move request
 // FIXME-NAV: This doesn't work properly with NavFlattened siblings as we use NavWindow rectangle for reference
diff --git a/imgui_internal.h b/imgui_internal.h
index 370f3cc..cd1ae96 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -2332,6 +2332,8 @@
     ImVector<ImGuiFocusScopeData> NavFocusRoute;                // Reversed copy focus scope stack for NavId (should contains NavFocusScopeId). This essentially follow the window->ParentWindowForFocusRoute chain.
     ImGuiID                 NavHighlightActivatedId;
     float                   NavHighlightActivatedTimer;
+    ImGuiID                 NavOpenContextMenuItemId;
+    ImGuiID                 NavOpenContextMenuWindowId;
     ImGuiID                 NavNextActivateId;                  // Set by ActivateItemByID(), queued until next frame.
     ImGuiActivateFlags      NavNextActivateFlags;
     ImGuiInputSource        NavInputSource;                     // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Gamepad
@@ -3332,7 +3334,7 @@
     IMGUI_API ImVec2        FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
     IMGUI_API ImGuiMouseButton GetMouseButtonFromPopupFlags(ImGuiPopupFlags flags);
     IMGUI_API bool          IsPopupOpenRequestForItem(ImGuiPopupFlags flags, ImGuiID id);
-    IMGUI_API bool          IsPopupOpenRequestForWindow(ImGuiPopupFlags flags, ImGuiID id);
+    IMGUI_API bool          IsPopupOpenRequestForWindow(ImGuiPopupFlags flags);
 
     // Tooltips
     IMGUI_API bool          BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags);