Skip to content

Commit 23ef6c1

Browse files
committed
Reworked modal/ctrl+tab dimming system to be entirely processed at end of the frame (backported 1dc3af3 from docking)
1 parent da3a36e commit 23ef6c1

File tree

3 files changed

+69
-39
lines changed

3 files changed

+69
-39
lines changed

Diff for: imgui.cpp

+67-38
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,8 @@ static bool UpdateWindowManualResize(ImGuiWindow* window, const ImVe
946946
static void RenderWindowOuterBorders(ImGuiWindow* window);
947947
static void RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar_rect, bool title_bar_is_highlight, int resize_grip_count, const ImU32 resize_grip_col[4], float resize_grip_draw_size);
948948
static void RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open);
949-
static void EndFrameDrawDimmedBackgrounds();
949+
static void RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32 col);
950+
static void RenderDimmedBackgrounds();
950951

951952
// Viewports
952953
static void UpdateViewportsNewFrame();
@@ -4442,9 +4443,58 @@ void ImGui::PopClipRect()
44424443
window->ClipRect = window->DrawList->_ClipRectStack.back();
44434444
}
44444445

4445-
static void ImGui::EndFrameDrawDimmedBackgrounds()
4446+
static void ImGui::RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32 col)
44464447
{
4447-
// (This is currently empty, left here to facilitate sync/merge with docking branch)
4448+
if ((col & IM_COL32_A_MASK) == 0)
4449+
return;
4450+
4451+
ImGuiViewportP* viewport = (ImGuiViewportP*)GetMainViewport();
4452+
ImRect viewport_rect = viewport->GetMainRect();
4453+
4454+
// Draw behind window by moving the draw command at the FRONT of the draw list
4455+
{
4456+
ImDrawList* draw_list = window->RootWindow->DrawList;
4457+
draw_list->AddDrawCmd();
4458+
draw_list->PushClipRect(viewport_rect.Min - ImVec2(1, 1), viewport_rect.Max + ImVec2(1, 1), false); // Ensure ImDrawCmd are not merged
4459+
draw_list->AddRectFilled(viewport_rect.Min, viewport_rect.Max, col);
4460+
ImDrawCmd cmd = draw_list->CmdBuffer.back();
4461+
IM_ASSERT(cmd.ElemCount == 6);
4462+
draw_list->CmdBuffer.pop_back();
4463+
draw_list->CmdBuffer.push_front(cmd);
4464+
}
4465+
}
4466+
4467+
static void ImGui::RenderDimmedBackgrounds()
4468+
{
4469+
ImGuiContext& g = *GImGui;
4470+
ImGuiWindow* modal_window = GetTopMostAndVisiblePopupModal();
4471+
const bool dim_bg_for_modal = (modal_window != NULL);
4472+
const bool dim_bg_for_window_list = (g.NavWindowingTargetAnim != NULL && g.NavWindowingTargetAnim->Active);
4473+
if (!dim_bg_for_modal && !dim_bg_for_window_list)
4474+
return;
4475+
4476+
if (dim_bg_for_modal)
4477+
{
4478+
// Draw dimming behind modal
4479+
RenderDimmedBackgroundBehindWindow(modal_window, GetColorU32(ImGuiCol_ModalWindowDimBg, g.DimBgRatio));
4480+
}
4481+
else if (dim_bg_for_window_list)
4482+
{
4483+
// Draw dimming behind CTRL+Tab target window
4484+
RenderDimmedBackgroundBehindWindow(g.NavWindowingTargetAnim, GetColorU32(ImGuiCol_NavWindowingDimBg, g.DimBgRatio));
4485+
4486+
// Draw border around CTRL+Tab target window
4487+
ImGuiWindow* window = g.NavWindowingTargetAnim;
4488+
ImGuiViewport* viewport = GetMainViewport();
4489+
float distance = g.FontSize;
4490+
ImRect bb = window->Rect();
4491+
bb.Expand(distance);
4492+
if (bb.GetWidth() >= viewport->Size.x && bb.GetHeight() >= viewport->Size.y)
4493+
bb.Expand(-distance - 1.0f); // If a window fits the entire viewport, adjust its highlight inward
4494+
window->DrawList->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size);
4495+
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), window->WindowRounding, 0, 3.0f);
4496+
window->DrawList->PopClipRect();
4497+
}
44484498
}
44494499

44504500
// This is normally called by Render(). You may want to call it directly if you want to avoid calling Render() but the gain will be very minimal.
@@ -4502,9 +4552,6 @@ void ImGui::EndFrame()
45024552
// Initiate moving window + handle left-click and right-click focus
45034553
UpdateMouseMovingWindowEndFrame();
45044554

4505-
// Draw modal/window whitening backgrounds
4506-
EndFrameDrawDimmedBackgrounds();
4507-
45084555
// Sort the window list so that all child windows are after their parent
45094556
// We cannot do that on FocusWindow() because children may not exist yet
45104557
g.WindowsTempSortBuffer.resize(0);
@@ -4574,6 +4621,10 @@ void ImGui::Render()
45744621
if (windows_to_render_top_most[n] && IsWindowActiveAndVisible(windows_to_render_top_most[n])) // NavWindowingTarget is always temporarily displayed as the top-most window
45754622
AddRootWindowToDrawData(windows_to_render_top_most[n]);
45764623

4624+
// Draw modal/window whitening backgrounds
4625+
if (first_render_of_frame)
4626+
RenderDimmedBackgrounds();
4627+
45774628
// Setup ImDrawData structures for end-user
45784629
g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = 0;
45794630
for (int n = 0; n < g.Viewports.Size; n++)
@@ -6248,24 +6299,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
62486299
window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID);
62496300
PushClipRect(host_rect.Min, host_rect.Max, false);
62506301

6251-
// Draw modal window background (darkens what is behind them, all viewports)
6252-
const bool dim_bg_for_modal = (flags & ImGuiWindowFlags_Modal) && window == GetTopMostPopupModal() && window->HiddenFramesCannotSkipItems <= 0;
6253-
const bool dim_bg_for_window_list = g.NavWindowingTargetAnim && (window == g.NavWindowingTargetAnim->RootWindow);
6254-
if (dim_bg_for_modal || dim_bg_for_window_list)
6255-
{
6256-
const ImU32 dim_bg_col = GetColorU32(dim_bg_for_modal ? ImGuiCol_ModalWindowDimBg : ImGuiCol_NavWindowingDimBg, g.DimBgRatio);
6257-
window->DrawList->AddRectFilled(viewport_rect.Min, viewport_rect.Max, dim_bg_col);
6258-
}
6259-
6260-
// Draw navigation selection/windowing rectangle background
6261-
if (dim_bg_for_window_list && window == g.NavWindowingTargetAnim)
6262-
{
6263-
ImRect bb = window->Rect();
6264-
bb.Expand(g.FontSize);
6265-
if (!bb.Contains(viewport_rect)) // Avoid drawing if the window covers all the viewport anyway
6266-
window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha * 0.25f), g.Style.WindowRounding);
6267-
}
6268-
62696302
// Child windows can render their decoration (bg color, border, scrollbars, etc.) within their parent to save a draw call (since 1.71)
62706303
// When using overlapping child windows, this will break the assumption that child z-order is mapped to submission order.
62716304
// FIXME: User code may rely on explicit sorting of overlapping child window and would need to disable this somehow. Please get in contact if you are affected (github #4493)
@@ -6293,20 +6326,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
62936326
window->DrawList = &window->DrawListInst;
62946327
}
62956328

6296-
// Draw navigation selection/windowing rectangle border
6297-
if (g.NavWindowingTargetAnim == window)
6298-
{
6299-
float rounding = ImMax(window->WindowRounding, g.Style.WindowRounding);
6300-
ImRect bb = window->Rect();
6301-
bb.Expand(g.FontSize);
6302-
if (bb.Contains(viewport_rect)) // If a window fits the entire viewport, adjust its highlight inward
6303-
{
6304-
bb.Expand(-g.FontSize - 1.0f);
6305-
rounding = window->WindowRounding;
6306-
}
6307-
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), rounding, 0, 3.0f);
6308-
}
6309-
63106329
// UPDATE RECTANGLES (2- THOSE AFFECTED BY SCROLLING)
63116330

63126331
// Work rectangle.
@@ -8363,6 +8382,16 @@ ImGuiWindow* ImGui::GetTopMostPopupModal()
83638382
return NULL;
83648383
}
83658384

8385+
ImGuiWindow* ImGui::GetTopMostAndVisiblePopupModal()
8386+
{
8387+
ImGuiContext& g = *GImGui;
8388+
for (int n = g.OpenPopupStack.Size - 1; n >= 0; n--)
8389+
if (ImGuiWindow* popup = g.OpenPopupStack.Data[n].Window)
8390+
if ((popup->Flags & ImGuiWindowFlags_Modal) && IsWindowActiveAndVisible(popup))
8391+
return popup;
8392+
return NULL;
8393+
}
8394+
83668395
void ImGui::OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags)
83678396
{
83688397
ImGuiContext& g = *GImGui;

Diff for: imgui.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ Index of this file:
6464
// Version
6565
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
6666
#define IMGUI_VERSION "1.86 WIP"
67-
#define IMGUI_VERSION_NUM 18513
67+
#define IMGUI_VERSION_NUM 18514
6868
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
6969
#define IMGUI_HAS_TABLE
7070

Diff for: imgui_internal.h

+1
Original file line numberDiff line numberDiff line change
@@ -2539,6 +2539,7 @@ namespace ImGui
25392539
IMGUI_API void BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags);
25402540
IMGUI_API ImRect GetPopupAllowedExtentRect(ImGuiWindow* window);
25412541
IMGUI_API ImGuiWindow* GetTopMostPopupModal();
2542+
IMGUI_API ImGuiWindow* GetTopMostAndVisiblePopupModal();
25422543
IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window);
25432544
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
25442545

0 commit comments

Comments
 (0)