|
@@ -961,6 +961,7 @@ static void RenderWindowDecorations(ImGuiWindow* window, const ImRec
|
|
static void RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open);
|
|
static void RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open);
|
|
static void RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32 col);
|
|
static void RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32 col);
|
|
static void RenderDimmedBackgrounds();
|
|
static void RenderDimmedBackgrounds();
|
|
|
|
+static ImGuiWindow* FindBlockingModal(ImGuiWindow* window);
|
|
|
|
|
|
// Viewports
|
|
// Viewports
|
|
const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID = 0x11111111; // Using an arbitrary constant instead of e.g. ImHashStr("ViewportDefault", 0); so it's easier to spot in the debugger. The exact value doesn't matter.
|
|
const ImGuiID IMGUI_VIEWPORT_DEFAULT_ID = 0x11111111; // Using an arbitrary constant instead of e.g. ImHashStr("ViewportDefault", 0); so it's easier to spot in the debugger. The exact value doesn't matter.
|
|
@@ -4043,7 +4044,7 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
|
|
|
|
|
|
// Modal windows prevents mouse from hovering behind them.
|
|
// Modal windows prevents mouse from hovering behind them.
|
|
ImGuiWindow* modal_window = GetTopMostPopupModal();
|
|
ImGuiWindow* modal_window = GetTopMostPopupModal();
|
|
- if (modal_window && g.HoveredWindow && !IsWindowChildOf(g.HoveredWindow->RootWindowDockTree, modal_window, true, true))
|
|
|
|
|
|
+ if (modal_window && g.HoveredWindow && !IsWindowWithinBeginStackOf(g.HoveredWindow->RootWindow, modal_window)) // FIXME-MERGE: RootWindowDockTree ?
|
|
clear_hovered_windows = true;
|
|
clear_hovered_windows = true;
|
|
|
|
|
|
// Disabled mouse?
|
|
// Disabled mouse?
|
|
@@ -4660,6 +4661,23 @@ static void ImGui::RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ImGuiWindow* ImGui::FindBottomMostVisibleWindowWithinBeginStack(ImGuiWindow* parent_window)
|
|
|
|
+{
|
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
|
+ ImGuiWindow* bottom_most_visible_window = parent_window;
|
|
|
|
+ for (int i = FindWindowDisplayIndex(parent_window); i >= 0; i--)
|
|
|
|
+ {
|
|
|
|
+ ImGuiWindow* window = g.Windows[i];
|
|
|
|
+ if (window->Flags & ImGuiWindowFlags_ChildWindow)
|
|
|
|
+ continue;
|
|
|
|
+ if (!IsWindowWithinBeginStackOf(window, parent_window))
|
|
|
|
+ break;
|
|
|
|
+ if (IsWindowActiveAndVisible(window) && GetWindowDisplayLayer(window) <= GetWindowDisplayLayer(parent_window))
|
|
|
|
+ bottom_most_visible_window = window;
|
|
|
|
+ }
|
|
|
|
+ return bottom_most_visible_window;
|
|
|
|
+}
|
|
|
|
+
|
|
static void ImGui::RenderDimmedBackgrounds()
|
|
static void ImGui::RenderDimmedBackgrounds()
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
@@ -4672,8 +4690,9 @@ static void ImGui::RenderDimmedBackgrounds()
|
|
ImGuiViewport* viewports_already_dimmed[2] = { NULL, NULL };
|
|
ImGuiViewport* viewports_already_dimmed[2] = { NULL, NULL };
|
|
if (dim_bg_for_modal)
|
|
if (dim_bg_for_modal)
|
|
{
|
|
{
|
|
- // Draw dimming behind modal
|
|
|
|
- RenderDimmedBackgroundBehindWindow(modal_window, GetColorU32(ImGuiCol_ModalWindowDimBg, g.DimBgRatio));
|
|
|
|
|
|
+ // Draw dimming behind modal or a begin stack child, whichever comes first in draw order.
|
|
|
|
+ ImGuiWindow* dim_behind_window = FindBottomMostVisibleWindowWithinBeginStack(modal_window);
|
|
|
|
+ RenderDimmedBackgroundBehindWindow(dim_behind_window, GetColorU32(ImGuiCol_ModalWindowDimBg, g.DimBgRatio));
|
|
viewports_already_dimmed[0] = modal_window->Viewport;
|
|
viewports_already_dimmed[0] = modal_window->Viewport;
|
|
}
|
|
}
|
|
else if (dim_bg_for_window_list)
|
|
else if (dim_bg_for_window_list)
|
|
@@ -6210,6 +6229,36 @@ void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// When a modal popup is open, newly created windows that want focus (i.e. are not popups and do not specify ImGuiWindowFlags_NoFocusOnAppearing)
|
|
|
|
+// should be positioned behind that modal window, unless the window was created inside the modal begin-stack.
|
|
|
|
+// In case of multiple stacked modals newly created window honors begin stack order and does not go below its own modal parent.
|
|
|
|
+// - Window // FindBlockingModal() returns Modal1
|
|
|
|
+// - Window // .. returns Modal1
|
|
|
|
+// - Modal1 // .. returns Modal2
|
|
|
|
+// - Window // .. returns Modal2
|
|
|
|
+// - Window // .. returns Modal2
|
|
|
|
+// - Modal2 // .. returns Modal2
|
|
|
|
+static ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window)
|
|
|
|
+{
|
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
|
+ if (g.OpenPopupStack.Size <= 0)
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ // Find a modal that has common parent with specified window. Specified window should be positioned behind that modal.
|
|
|
|
+ for (int i = g.OpenPopupStack.Size - 1; i >= 0; i--)
|
|
|
|
+ {
|
|
|
|
+ ImGuiWindow* popup_window = g.OpenPopupStack.Data[i].Window;
|
|
|
|
+ if (popup_window == NULL || !popup_window->WasActive || !(popup_window->Flags & ImGuiWindowFlags_Modal)) // Check WasActive, because this code may run before popup renders on current frame.
|
|
|
|
+ continue;
|
|
|
|
+ if (IsWindowWithinBeginStackOf(window, popup_window)) // Window is rendered over last modal, no render order change needed.
|
|
|
|
+ break;
|
|
|
|
+ for (ImGuiWindow* parent = popup_window->ParentWindowInBeginStack->RootWindow; parent != NULL; parent = parent->ParentWindowInBeginStack->RootWindow)
|
|
|
|
+ if (IsWindowWithinBeginStackOf(window, parent))
|
|
|
|
+ return popup_window; // Place window above its begin stack parent.
|
|
|
|
+ }
|
|
|
|
+ return NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
// Push a new Dear ImGui window to add widgets to.
|
|
// Push a new Dear ImGui window to add widgets to.
|
|
// - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair.
|
|
// - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair.
|
|
// - Begin/End can be called multiple times during the frame with the same window name to append content.
|
|
// - Begin/End can be called multiple times during the frame with the same window name to append content.
|
|
@@ -6645,6 +6694,22 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
want_focus = true;
|
|
want_focus = true;
|
|
else if ((window->DockIsActive || (flags & ImGuiWindowFlags_ChildWindow) == 0) && !(flags & ImGuiWindowFlags_Tooltip))
|
|
else if ((window->DockIsActive || (flags & ImGuiWindowFlags_ChildWindow) == 0) && !(flags & ImGuiWindowFlags_Tooltip))
|
|
want_focus = true;
|
|
want_focus = true;
|
|
|
|
+
|
|
|
|
+ ImGuiWindow* modal = GetTopMostPopupModal();
|
|
|
|
+ if (modal != NULL && !IsWindowWithinBeginStackOf(window, modal))
|
|
|
|
+ {
|
|
|
|
+ // Avoid focusing a window that is created outside of active modal. This will prevent active modal from being closed.
|
|
|
|
+ // Since window is not focused it would reappear at the same display position like the last time it was visible.
|
|
|
|
+ // In case of completely new windows it would go to the top (over current modal), but input to such window would still be blocked by modal.
|
|
|
|
+ // Position window behind a modal that is not a begin-parent of this window.
|
|
|
|
+ want_focus = false;
|
|
|
|
+ if (window == window->RootWindow)
|
|
|
|
+ {
|
|
|
|
+ ImGuiWindow* blocking_modal = FindBlockingModal(window);
|
|
|
|
+ IM_ASSERT(blocking_modal != NULL);
|
|
|
|
+ BringWindowToDisplayBehind(window, blocking_modal);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
// Decide if we are going to handle borders and resize grips
|
|
// Decide if we are going to handle borders and resize grips
|
|
@@ -7101,6 +7166,34 @@ void ImGui::BringWindowToDisplayBack(ImGuiWindow* window)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void ImGui::BringWindowToDisplayBehind(ImGuiWindow* window, ImGuiWindow* behind_window)
|
|
|
|
+{
|
|
|
|
+ IM_ASSERT(window != NULL && behind_window != NULL);
|
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
|
+ window = window->RootWindow;
|
|
|
|
+ behind_window = behind_window->RootWindow;
|
|
|
|
+ int pos_wnd = FindWindowDisplayIndex(window);
|
|
|
|
+ int pos_beh = FindWindowDisplayIndex(behind_window);
|
|
|
|
+ if (pos_wnd < pos_beh)
|
|
|
|
+ {
|
|
|
|
+ size_t copy_bytes = (pos_beh - pos_wnd - 1) * sizeof(ImGuiWindow*);
|
|
|
|
+ memmove(&g.Windows.Data[pos_wnd], &g.Windows.Data[pos_wnd + 1], copy_bytes);
|
|
|
|
+ g.Windows[pos_beh - 1] = window;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ size_t copy_bytes = (pos_wnd - pos_beh) * sizeof(ImGuiWindow*);
|
|
|
|
+ memmove(&g.Windows.Data[pos_beh + 1], &g.Windows.Data[pos_beh], copy_bytes);
|
|
|
|
+ g.Windows[pos_beh] = window;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int ImGui::FindWindowDisplayIndex(ImGuiWindow* window)
|
|
|
|
+{
|
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
|
+ return g.Windows.index_from_ptr(g.Windows.find(window));
|
|
|
|
+}
|
|
|
|
+
|
|
// Moving window to front of display and set focus (which happens to be back of our sorted list)
|
|
// Moving window to front of display and set focus (which happens to be back of our sorted list)
|
|
void ImGui::FocusWindow(ImGuiWindow* window)
|
|
void ImGui::FocusWindow(ImGuiWindow* window)
|
|
{
|
|
{
|
|
@@ -7344,6 +7437,19 @@ bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent,
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+bool ImGui::IsWindowWithinBeginStackOf(ImGuiWindow* window, ImGuiWindow* potential_parent)
|
|
|
|
+{
|
|
|
|
+ if (window->RootWindow == potential_parent)
|
|
|
|
+ return true;
|
|
|
|
+ while (window != NULL)
|
|
|
|
+ {
|
|
|
|
+ if (window == potential_parent)
|
|
|
|
+ return true;
|
|
|
|
+ window = window->ParentWindowInBeginStack;
|
|
|
|
+ }
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
bool ImGui::IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below)
|
|
bool ImGui::IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below)
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
@@ -9117,7 +9223,8 @@ void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to
|
|
bool ref_window_is_descendent_of_popup = false;
|
|
bool ref_window_is_descendent_of_popup = false;
|
|
for (int n = popup_count_to_keep; n < g.OpenPopupStack.Size; n++)
|
|
for (int n = popup_count_to_keep; n < g.OpenPopupStack.Size; n++)
|
|
if (ImGuiWindow* popup_window = g.OpenPopupStack[n].Window)
|
|
if (ImGuiWindow* popup_window = g.OpenPopupStack[n].Window)
|
|
- if (popup_window->RootWindowDockTree == ref_window->RootWindowDockTree)
|
|
|
|
|
|
+ //if (popup_window->RootWindowDockTree == ref_window->RootWindowDockTree) // FIXME-MERGE
|
|
|
|
+ if (IsWindowWithinBeginStackOf(ref_window, popup_window))
|
|
{
|
|
{
|
|
ref_window_is_descendent_of_popup = true;
|
|
ref_window_is_descendent_of_popup = true;
|
|
break;
|
|
break;
|