diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 44735b0d..df364f32 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -118,9 +118,10 @@ Other Changes: rather than the Mouse Down+Up sequence, even if the _OpenOnArrow flag isn't set. This is standard behavior and amends the change done in 1.76 which only affected cases were _OpenOnArrow flag was set. (This is also necessary to support full multi/range-select/drag and drop operations.) +- Tab Bar: Keep tab item close button visible while dragging a tab (independent of hovering state). - Metrics: Various tweaks, listing windows front-to-back, greying inactive items when possible. - Demo: Add simple InputText() callbacks demo (aside from the more elaborate ones in 'Examples->Console'). ->>>>>>> master +- Examples: Vulkan: Reworked buffer resize handling, fix for Linux/X11. (#3390, #2626) [@RoryO] ----------------------------------------------------------------------- diff --git a/docs/TODO.txt b/docs/TODO.txt index 296e6a44..52c531f1 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -197,7 +197,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - tabs: "there is currently a problem because TabItem() will try to submit their own tooltip after 0.50 second, and this will have the effect of making your tooltip flicker once." -> tooltip priority work - tabs: close button tends to overlap unsaved-document star - tabs: consider showing the star at the same spot as the close button, like VS Code does. - - tabs: while dragging/reordering a tab, close button decoration shouldn't appear on other tabs - tabs: make EndTabBar fail if users doesn't respect BeginTabBar return value, for consistency/future-proofing. - tabs: persistent order/focus in BeginTabBar() api (#261, #351) - tabs: TabItem could honor SetNextItemWidth()? diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index f85390ea..080caad9 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -310,7 +310,7 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data) } } -static void FramePresent(ImGui_ImplVulkanH_Window* wd) +static void FramePresent(ImGui_ImplVulkanH_Window* wd, GLFWwindow* window) { VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore; VkPresentInfoKHR info = {}; @@ -321,6 +321,12 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd) info.pSwapchains = &wd->Swapchain; info.pImageIndices = &wd->FrameIndex; VkResult err = vkQueuePresentKHR(g_Queue, &info); + if (err == VK_ERROR_OUT_OF_DATE_KHR) + { + glfwGetFramebufferSize(window, &g_SwapChainResizeWidth, &g_SwapChainResizeHeight); + g_SwapChainRebuild = true; + return; + } check_vk_result(err); wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores } @@ -330,13 +336,6 @@ static void glfw_error_callback(int error, const char* description) fprintf(stderr, "Glfw Error %d: %s\n", error, description); } -static void glfw_resize_callback(GLFWwindow*, int w, int h) -{ - g_SwapChainRebuild = true; - g_SwapChainResizeWidth = w; - g_SwapChainResizeHeight = h; -} - int main(int, char**) { // Setup GLFW window @@ -365,7 +364,6 @@ int main(int, char**) // Create Framebuffers int w, h; glfwGetFramebufferSize(window, &w, &h); - glfwSetFramebufferSizeCallback(window, glfw_resize_callback); ImGui_ImplVulkanH_Window* wd = &g_MainWindowData; SetupVulkanWindow(wd, surface, w, h); diff --git a/examples/example_sdl_vulkan/main.cpp b/examples/example_sdl_vulkan/main.cpp index 699d3c28..0024594a 100644 --- a/examples/example_sdl_vulkan/main.cpp +++ b/examples/example_sdl_vulkan/main.cpp @@ -302,7 +302,7 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data) } } -static void FramePresent(ImGui_ImplVulkanH_Window* wd) +static void FramePresent(ImGui_ImplVulkanH_Window* wd, SDL_Window* window) { VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore; VkPresentInfoKHR info = {}; @@ -313,6 +313,12 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd) info.pSwapchains = &wd->Swapchain; info.pImageIndices = &wd->FrameIndex; VkResult err = vkQueuePresentKHR(g_Queue, &info); + if (err == VK_ERROR_OUT_OF_DATE_KHR) + { + SDL_GetWindowSize(window, &g_SwapChainResizeWidth, &g_SwapChainResizeHeight); + g_SwapChainRebuild = true; + return; + } check_vk_result(err); wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores } @@ -457,15 +463,6 @@ int main(int, char**) ImGui_ImplSDL2_ProcessEvent(&event); if (event.type == SDL_QUIT) done = true; - if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED && event.window.windowID == SDL_GetWindowID(window)) - { - // Note: your own application may rely on SDL_WINDOWEVENT_MINIMIZED/SDL_WINDOWEVENT_RESTORED to skip updating all-together. - // Here ImGui_ImplSDL2_NewFrame() will set io.DisplaySize to zero which will disable rendering but let application run. - // Please note that you can't Present into a minimized window. - g_SwapChainResizeWidth = (int)event.window.data1; - g_SwapChainResizeHeight = (int)event.window.data2; - g_SwapChainRebuild = true; - } } // Resize swap chain? diff --git a/imgui.cpp b/imgui.cpp index 15749d3a..c0279359 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3789,17 +3789,18 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags() // - Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow. // - When moving a window we can skip the search, which also conveniently bypasses the fact that window->WindowRectClipped is lagging as this point of the frame. // - We also support the moved window toggling the NoInputs flag after moving has started in order to be able to detect windows below it, which is useful for e.g. docking mechanisms. + bool clear_hovered_windows = false; FindHoveredWindow(); IM_ASSERT(g.HoveredWindow == NULL || g.HoveredWindow == g.MovingWindow || g.HoveredWindow->Viewport == g.MouseViewport); // Modal windows prevents mouse from hovering behind them. ImGuiWindow* modal_window = GetTopMostPopupModal(); if (modal_window && g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window)) - g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL; + clear_hovered_windows = true; // Disabled mouse? if (g.IO.ConfigFlags & ImGuiConfigFlags_NoMouse) - g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL; + clear_hovered_windows = true; // We track click ownership. When clicked outside of a window the click is owned by the application and won't report hovering nor request capture even while dragging over our windows afterward. int mouse_earliest_button_down = -1; @@ -3819,6 +3820,9 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags() // FIXME: For patterns of drag and drop across OS windows, we may need to rework/remove this test (first committed 311c0ca9 on 2015/02) const bool mouse_dragging_extern_payload = g.DragDropActive && (g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0; if (!mouse_avail_to_imgui && !mouse_dragging_extern_payload) + clear_hovered_windows = true; + + if (clear_hovered_windows) g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL; // Update io.WantCaptureMouse for the user application (true = dispatch mouse info to imgui, false = dispatch mouse info to Dear ImGui + app) @@ -8108,7 +8112,7 @@ ImVec2 ImGui::ScrollToBringRectIntoView(ImGuiWindow* window, const ImRect& item_ if (!window_rect.Contains(item_rect)) { if (window->ScrollbarX && item_rect.Min.x < window_rect.Min.x) - SetScrollFromPosX(window, item_rect.Min.x - window->Pos.x + g.Style.ItemSpacing.x, 0.0f); + SetScrollFromPosX(window, item_rect.Min.x - window->Pos.x - g.Style.ItemSpacing.x, 0.0f); else if (window->ScrollbarX && item_rect.Max.x >= window_rect.Max.x) SetScrollFromPosX(window, item_rect.Max.x - window->Pos.x + g.Style.ItemSpacing.x, 1.0f); if (item_rect.Min.y < window_rect.Min.y) @@ -9859,10 +9863,11 @@ static void ImGui::NavUpdateWindowing() if (move_delta.x != 0.0f || move_delta.y != 0.0f) { const float NAV_MOVE_SPEED = 800.0f; - const float move_speed = ImFloor(NAV_MOVE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); // FIXME: Doesn't code variable framerate very well - SetWindowPos(g.NavWindowingTarget->RootWindow, g.NavWindowingTarget->RootWindow->Pos + move_delta * move_speed, ImGuiCond_Always); + const float move_speed = ImFloor(NAV_MOVE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); // FIXME: Doesn't handle variable framerate very well + ImGuiWindow* moving_window = g.NavWindowingTarget->RootWindow; + SetWindowPos(moving_window, moving_window->Pos + move_delta * move_speed, ImGuiCond_Always); + MarkIniSettingsDirty(moving_window); g.NavDisableMouseHover = true; - MarkIniSettingsDirty(g.NavWindowingTarget); } } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 45553465..07902c10 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1630,7 +1630,7 @@ static void ShowDemoWindowWidgets() static int slider_i = 50; ImGui::Text("Underlying float value: %f", slider_f); ImGui::SliderFloat("SliderFloat (0 -> 1)", &slider_f, 0.0f, 1.0f, "%.3f", flags); - ImGui::SliderInt("SliderInt (0 -> 100)", &slider_i, 0, 100, "%.3f", flags); + ImGui::SliderInt("SliderInt (0 -> 100)", &slider_i, 0, 100, "%d", flags); ImGui::TreePop(); } @@ -1875,7 +1875,7 @@ static void ShowDemoWindowWidgets() if (ImGui::RadioButton("Copy", mode == Mode_Copy)) { mode = Mode_Copy; } ImGui::SameLine(); if (ImGui::RadioButton("Move", mode == Mode_Move)) { mode = Mode_Move; } ImGui::SameLine(); if (ImGui::RadioButton("Swap", mode == Mode_Swap)) { mode = Mode_Swap; } - const char* names[9] = + static const char* names[9] = { "Bobby", "Beatrice", "Betty", "Brianna", "Barry", "Bernard", diff --git a/imgui_internal.h b/imgui_internal.h index 5ccf0581..a32e8dcd 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -654,12 +654,13 @@ enum ImGuiSliderFlagsPrivate_ enum ImGuiSelectableFlagsPrivate_ { // NB: need to be in sync with last value of ImGuiSelectableFlags_ - ImGuiSelectableFlags_NoHoldingActiveID = 1 << 20, - ImGuiSelectableFlags_SelectOnClick = 1 << 21, // Override button behavior to react on Click (default is Click+Release) - ImGuiSelectableFlags_SelectOnRelease = 1 << 22, // Override button behavior to react on Release (default is Click+Release) - ImGuiSelectableFlags_SpanAvailWidth = 1 << 23, // Span all avail width even if we declared less for layout purpose. FIXME: We may be able to remove this (added in 6251d379, 2bcafc86 for menus) - ImGuiSelectableFlags_DrawHoveredWhenHeld= 1 << 24, // Always show active when held, even is not hovered. This concept could probably be renamed/formalized somehow. - ImGuiSelectableFlags_SetNavIdOnHover = 1 << 25 + ImGuiSelectableFlags_NoHoldingActiveID = 1 << 20, + ImGuiSelectableFlags_SelectOnClick = 1 << 21, // Override button behavior to react on Click (default is Click+Release) + ImGuiSelectableFlags_SelectOnRelease = 1 << 22, // Override button behavior to react on Release (default is Click+Release) + ImGuiSelectableFlags_SpanAvailWidth = 1 << 23, // Span all avail width even if we declared less for layout purpose. FIXME: We may be able to remove this (added in 6251d379, 2bcafc86 for menus) + ImGuiSelectableFlags_DrawHoveredWhenHeld = 1 << 24, // Always show active when held, even is not hovered. This concept could probably be renamed/formalized somehow. + ImGuiSelectableFlags_SetNavIdOnHover = 1 << 25, // Set Nav/Focus ID on mouse hover (used by MenuItem) + ImGuiSelectableFlags_NoPadWithHalfSpacing = 1 << 26 // Disable padding each side with ItemSpacing * 0.5f }; // Extend ImGuiTreeNodeFlags_ @@ -1366,11 +1367,11 @@ struct ImGuiContext ImGuiKeyModFlags NavJustMovedToKeyMods; ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame. ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard. - ImRect NavScoringRect; // Rectangle used for scoring, in screen space. Based of window->DC.NavRefRectRel[], modified for directional navigation scoring. + ImRect NavScoringRect; // Rectangle used for scoring, in screen space. Based of window->NavRectRel[], modified for directional navigation scoring. int NavScoringCount; // Metrics for debugging ImGuiNavLayer NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing - bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRefRectRel is valid + bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRectRel is valid bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default) bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (NB: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover) bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 9dfa7609..a3062041 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5899,7 +5899,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns) // FIXME-OPT: Avoid if vertically clipped. + const bool span_all_columns = (flags & ImGuiSelectableFlags_SpanAllColumns) != 0; + if (span_all_columns && window->DC.CurrentColumns) // FIXME-OPT: Avoid if vertically clipped. PushColumnsBackground(); // Submit label or explicit size to ItemSize(), whereas ItemAdd() will submit a larger/spanning rectangle. @@ -5911,8 +5912,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl ItemSize(size, 0.0f); // Fill horizontal space - const float min_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? window->ParentWorkRect.Min.x : pos.x; - const float max_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? window->ParentWorkRect.Max.x : window->WorkRect.Max.x; + const float min_x = span_all_columns ? window->ParentWorkRect.Min.x : pos.x; + const float max_x = span_all_columns ? window->ParentWorkRect.Max.x : window->WorkRect.Max.x; if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_SpanAvailWidth)) size.x = ImMax(label_size.x, max_x - min_x); @@ -5921,33 +5922,35 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl const ImVec2 text_max(min_x + size.x, pos.y + size.y); // Selectables are meant to be tightly packed together with no click-gap, so we extend their box to cover spacing between selectable. - ImRect bb_enlarged(min_x, pos.y, text_max.x, text_max.y); - const float spacing_x = style.ItemSpacing.x; - const float spacing_y = style.ItemSpacing.y; - const float spacing_L = IM_FLOOR(spacing_x * 0.50f); - const float spacing_U = IM_FLOOR(spacing_y * 0.50f); - bb_enlarged.Min.x -= spacing_L; - bb_enlarged.Min.y -= spacing_U; - bb_enlarged.Max.x += (spacing_x - spacing_L); - bb_enlarged.Max.y += (spacing_y - spacing_U); - //if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb_align.Min, bb_align.Max, IM_COL32(255, 0, 0, 255)); } - //if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb_enlarged.Min, bb_enlarged.Max, IM_COL32(0, 255, 0, 255)); } + ImRect bb(min_x, pos.y, text_max.x, text_max.y); + if ((flags & ImGuiSelectableFlags_NoPadWithHalfSpacing) == 0) + { + const float spacing_x = style.ItemSpacing.x; + const float spacing_y = style.ItemSpacing.y; + const float spacing_L = IM_FLOOR(spacing_x * 0.50f); + const float spacing_U = IM_FLOOR(spacing_y * 0.50f); + bb.Min.x -= spacing_L; + bb.Min.y -= spacing_U; + bb.Max.x += (spacing_x - spacing_L); + bb.Max.y += (spacing_y - spacing_U); + } + //if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(0, 255, 0, 255)); } bool item_add; if (flags & ImGuiSelectableFlags_Disabled) { ImGuiItemFlags backup_item_flags = window->DC.ItemFlags; window->DC.ItemFlags |= ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNavDefaultFocus; - item_add = ItemAdd(bb_enlarged, id); + item_add = ItemAdd(bb, id); window->DC.ItemFlags = backup_item_flags; } else { - item_add = ItemAdd(bb_enlarged, id); + item_add = ItemAdd(bb, id); } if (!item_add) { - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns) + if (span_all_columns && window->DC.CurrentColumns) PopColumnsBackground(); return false; } @@ -5966,7 +5969,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl const bool was_selected = selected; bool hovered, held; - bool pressed = ButtonBehavior(bb_enlarged, id, &hovered, &held, button_flags); + bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover))) @@ -5993,15 +5996,15 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl if (hovered || selected) { const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); - RenderFrame(bb_enlarged.Min, bb_enlarged.Max, col, false, 0.0f); - RenderNavHighlight(bb_enlarged, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); + RenderFrame(bb.Min, bb.Max, col, false, 0.0f); + RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); } - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns) + if (span_all_columns && window->DC.CurrentColumns) PopColumnsBackground(); if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); - RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb_enlarged); + RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb); if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor(); // Automatically close popups @@ -7749,7 +7752,7 @@ bool ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, bool close_button_visible = false; if (close_button_id != 0) if (is_contents_visible || bb.GetWidth() >= g.Style.TabMinWidthForUnselectedCloseButton) - if (g.HoveredId == tab_id || g.HoveredId == close_button_id || g.ActiveId == close_button_id) + if (g.HoveredId == tab_id || g.HoveredId == close_button_id || g.ActiveId == tab_id || g.ActiveId == close_button_id) close_button_visible = true; if (close_button_visible) {