diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b2c9f652..a789f71f 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -115,6 +115,10 @@ Other changes: (#6341) [@lukaasm] - Nav: Fixed navigation within tables/columns where item boundaries goes beyond columns limits, unclipped bounding boxes would interfere with other columns. (#2221) [@zzzyap, @ocornut] +- Nav: Fixed CTRL+Tab into a root window with only childs with _NavFlattened flags + erroneously initializing default nav layer to menu layer. +- Menus: Fixed an issue when opening a menu hierarchy in a given menu-bar would allow + opening another via simple hovering. (#3496, #4797) - Debug Tools: Debug Log: Fixed not parsing 0xXXXXXXXX values for geo-locating on mouse hover hover when the identifier is at the end of the line. (#5855) - Backends: Clear bits sets io.BackendFlags on backend Shutdown(). (#6334, #6335] [@GereonV] @@ -125,6 +129,7 @@ Other changes: by context (Desktop 3.0, 3.1, or 3.2+ with compat bit). (#6333) [@GereonV] - Examples: Added native Win32+OpenGL3 example. We don't recommend using this setup but we provide it for completeness. (#3218, #5170, #6086, #2772, #2600, #2359, #2022, #1553) [@learn-more] +- Examples: Vulkan: Use integrated GPU if nothing else is available. (#6359) [@kimidaisuki22] Docking+Viewports Branch: diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index 8f749082..769966c4 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -99,6 +99,10 @@ static VkPhysicalDevice SetupVulkan_SelectPhysicalDevice() if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) return device; } + + // Use first GPU (Integrated) is a Discrete one is not available. + if (gpu_count > 0) + return gpus[0]; return VK_NULL_HANDLE; } diff --git a/examples/example_glut_opengl2/main.cpp b/examples/example_glut_opengl2/main.cpp index e5f45520..b2344a78 100644 --- a/examples/example_glut_opengl2/main.cpp +++ b/examples/example_glut_opengl2/main.cpp @@ -108,6 +108,7 @@ void MainLoopStep() ImGui_ImplOpenGL2_NewFrame(); ImGui_ImplGLUT_NewFrame(); ImGui::NewFrame(); + ImGuiIO& io = ImGui::GetIO(); // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!). if (show_demo_window) @@ -148,7 +149,6 @@ void MainLoopStep() // Rendering ImGui::Render(); - ImGuiIO& io = ImGui::GetIO(); glViewport(0, 0, (GLsizei)io.DisplaySize.x, (GLsizei)io.DisplaySize.y); glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w); glClear(GL_COLOR_BUFFER_BIT); diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index 12a6f90b..642ce29d 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -87,6 +87,10 @@ static VkPhysicalDevice SetupVulkan_SelectPhysicalDevice() if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) return device; } + + // Use first GPU (Integrated) is a Discrete one is not available. + if (gpu_count > 0) + return gpus[0]; return VK_NULL_HANDLE; } diff --git a/imgui.cpp b/imgui.cpp index 569c08ab..489ea037 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5642,6 +5642,10 @@ void ImGui::EndChild() { // Not navigable into ItemAdd(bb, 0); + + // But when flattened we directly reach items, adjust active layer mask accordingly + if (window->Flags & ImGuiWindowFlags_NavFlattened) + parent_window->DC.NavLayersActiveMaskNext |= window->DC.NavLayersActiveMaskNext; } if (g.HoveredWindow == window) g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_HoveredWindow; @@ -7456,7 +7460,7 @@ void ImGui::FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags) ImGuiContext& g = *GImGui; // Modal check? - if (flags & ImGuiFocusRequestFlags_UnlessBelowModal) + if ((flags & ImGuiFocusRequestFlags_UnlessBelowModal) && (g.NavWindow != window)) // Early out in common case. if (ImGuiWindow* blocking_modal = FindBlockingModal(window)) { IMGUI_DEBUG_LOG_FOCUS("[focus] FocusWindow(\"%s\", UnlessBelowModal): prevented by \"%s\".\n", window ? window->Name : "", blocking_modal->Name); @@ -11330,20 +11334,6 @@ static float inline NavScoreItemDistInterval(float cand_min, float cand_max, flo return 0.0f; } -static void inline NavClampRectToVisibleAreaForMoveDir(ImGuiDir move_dir, ImRect& r, const ImRect& clip_rect) -{ - if (move_dir == ImGuiDir_Left || move_dir == ImGuiDir_Right) - { - r.Min.y = ImClamp(r.Min.y, clip_rect.Min.y, clip_rect.Max.y); - r.Max.y = ImClamp(r.Max.y, clip_rect.Min.y, clip_rect.Max.y); - } - else // FIXME: PageUp/PageDown are leaving move_dir == None - { - r.Min.x = ImClamp(r.Min.x, clip_rect.Min.x, clip_rect.Max.x); - r.Max.x = ImClamp(r.Max.x, clip_rect.Min.x, clip_rect.Max.x); - } -} - // Scoring function for gamepad/keyboard directional navigation. Based on https://gist.github.com/rygorous/6981057 static bool ImGui::NavScoreItem(ImGuiNavItemData* result) { @@ -11366,10 +11356,6 @@ static bool ImGui::NavScoreItem(ImGuiNavItemData* result) cand.ClipWithFull(window->ClipRect); // This allows the scored item to not overlap other candidates in the parent window } - // We perform scoring on items bounding box clipped by the current clipping rectangle on the other axis (clipping on our movement axis would give us equal scores for all clipped items) - // For example, this ensures that items in one column are not reached when moving vertically from items in another column. - NavClampRectToVisibleAreaForMoveDir(g.NavMoveClipDir, cand, window->ClipRect); - // Compute distance between boxes // FIXME-NAV: Introducing biases for vertical navigation, needs to be removed. float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x); @@ -11697,10 +11683,11 @@ void ImGui::NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNav void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags wrap_flags) { ImGuiContext& g = *GImGui; - IM_ASSERT(wrap_flags != 0); // Call with _WrapX, _WrapY, _LoopX, _LoopY + IM_ASSERT((wrap_flags & ImGuiNavMoveFlags_WrapMask_ ) != 0 && (wrap_flags & ~ImGuiNavMoveFlags_WrapMask_) == 0); // Call with _WrapX, _WrapY, _LoopX, _LoopY + // In theory we should test for NavMoveRequestButNoResultYet() but there's no point doing it, NavEndFrame() will do the same test if (g.NavWindow == window && g.NavMoveScoringItems && g.NavLayer == ImGuiNavLayer_Main) - g.NavMoveFlags |= wrap_flags; + g.NavMoveFlags = (g.NavMoveFlags & ~ImGuiNavMoveFlags_WrapMask_) | wrap_flags; } // FIXME: This could be replaced by updating a frame number in each window when (window == NavWindow) and (NavLayer == 0). @@ -12398,8 +12385,7 @@ static void ImGui::NavEndFrame() // Perform wrap-around in menus // FIXME-NAV: Wrap may need to apply a weight bias on the other axis. e.g. 4x4 grid with 2 last items missing on last item won't handle LoopY/WrapY correctly. // FIXME-NAV: Wrap (not Loop) support could be handled by the scoring function and then WrapX would function without an extra frame. - const ImGuiNavMoveFlags wanted_flags = ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_LoopX | ImGuiNavMoveFlags_WrapY | ImGuiNavMoveFlags_LoopY; - if (g.NavWindow && NavMoveRequestButNoResultYet() && (g.NavMoveFlags & wanted_flags) && (g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded) == 0) + if (g.NavWindow && NavMoveRequestButNoResultYet() && (g.NavMoveFlags & ImGuiNavMoveFlags_WrapMask_) && (g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded) == 0) NavUpdateCreateWrappingRequest(); } @@ -12508,7 +12494,7 @@ static void ImGui::NavUpdateWindowing() bool apply_toggle_layer = false; ImGuiWindow* modal_window = GetTopMostPopupModal(); - bool allow_windowing = (modal_window == NULL); // FIXME: This prevent CTRL+TAB from being usable with windows over a popup + bool allow_windowing = (modal_window == NULL); // FIXME: This prevent CTRL+TAB from being usable with windows that are inside the Begin-stack of that modal. if (!allow_windowing) g.NavWindowingTarget = NULL; @@ -13422,6 +13408,7 @@ void ImGui::LoadIniSettingsFromDisk(const char* ini_filename) } // Zero-tolerance, no error reporting, cheap .ini parsing +// Set ini_size==0 to let us use strlen(ini_data). Do not call this function with a 0 if your buffer is actually empty! void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size) { ImGuiContext& g = *GImGui; diff --git a/imgui.h b/imgui.h index 38948f6c..ca5bc9bc 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.6 WIP" -#define IMGUI_VERSION_NUM 18953 +#define IMGUI_VERSION_NUM 18954 #define IMGUI_HAS_TABLE #define IMGUI_HAS_VIEWPORT // Viewport WIP branch #define IMGUI_HAS_DOCK // Docking WIP branch diff --git a/imgui_internal.h b/imgui_internal.h index bd23b47f..b32a3e42 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1494,6 +1494,7 @@ enum ImGuiNavMoveFlags_ ImGuiNavMoveFlags_LoopY = 1 << 1, ImGuiNavMoveFlags_WrapX = 1 << 2, // On failed request, request from opposite side one line down (when NavDir==right) or one line up (when NavDir==left) ImGuiNavMoveFlags_WrapY = 1 << 3, // This is not super useful but provided for completeness + ImGuiNavMoveFlags_WrapMask_ = ImGuiNavMoveFlags_LoopX | ImGuiNavMoveFlags_LoopY | ImGuiNavMoveFlags_WrapX | ImGuiNavMoveFlags_WrapY, ImGuiNavMoveFlags_AllowCurrentNavId = 1 << 4, // Allow scoring and considering the current NavId as a move target candidate. This is used when the move source is offset (e.g. pressing PageDown actually needs to send a Up move request, if we are pressing PageDown from the bottom-most item we need to stay in place) ImGuiNavMoveFlags_AlsoScoreVisibleSet = 1 << 5, // Store alternate result in NavMoveResultLocalVisible that only comprise elements that are already fully visible (used by PageUp/PageDown) ImGuiNavMoveFlags_ScrollToEdgeY = 1 << 6, // Force scrolling to min/max (used by Home/End) // FIXME-NAV: Aim to remove or reword, probably unnecessary diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 211368c1..f501c21a 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7109,9 +7109,9 @@ static bool IsRootOfOpenMenuSet() // 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. PushID() user code submitting menus. // 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 // 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. @@ -7119,7 +7119,9 @@ static bool IsRootOfOpenMenuSet() // 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]; - return (window->DC.NavLayerCurrent == upper_popup->ParentNavLayer && upper_popup->Window && (upper_popup->Window->Flags & ImGuiWindowFlags_ChildMenu)); + if (window->DC.NavLayerCurrent != upper_popup->ParentNavLayer) + return false; + return upper_popup->Window && (upper_popup->Window->Flags & ImGuiWindowFlags_ChildMenu) && ImGui::IsWindowChildOf(upper_popup->Window, window, true); } bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)