|
|
@@ -2469,6 +2469,7 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx)
|
|
|
return "Unknown";
|
|
|
}
|
|
|
|
|
|
+
|
|
|
//-----------------------------------------------------------------------------
|
|
|
// [SECTION] RENDER HELPERS
|
|
|
// Some of those (internal) functions are currently quite a legacy mess - their signature and behavior will change,
|
|
|
@@ -3594,15 +3595,14 @@ void ImGui::UpdateHoveredWindowAndCaptureFlags()
|
|
|
// - 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.
|
|
|
FindHoveredWindow();
|
|
|
|
|
|
- // Modal windows prevents cursor from hovering behind them.
|
|
|
+ // Modal windows prevents mouse from hovering behind them.
|
|
|
ImGuiWindow* modal_window = GetTopMostPopupModal();
|
|
|
- if (modal_window)
|
|
|
- if (g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window))
|
|
|
- g.HoveredRootWindow = g.HoveredWindow = NULL;
|
|
|
+ if (modal_window && g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window))
|
|
|
+ g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL;
|
|
|
|
|
|
// Disabled mouse?
|
|
|
if (g.IO.ConfigFlags & ImGuiConfigFlags_NoMouse)
|
|
|
- g.HoveredWindow = g.HoveredRootWindow = NULL;
|
|
|
+ g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL;
|
|
|
|
|
|
// 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;
|
|
|
@@ -3622,7 +3622,7 @@ 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)
|
|
|
- g.HoveredWindow = g.HoveredRootWindow = NULL;
|
|
|
+ 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)
|
|
|
if (g.WantCaptureMouseNextFrame != -1)
|
|
|
@@ -3936,7 +3936,7 @@ void ImGui::Shutdown(ImGuiContext* context)
|
|
|
g.CurrentWindowStack.clear();
|
|
|
g.WindowsById.Clear();
|
|
|
g.NavWindow = NULL;
|
|
|
- g.HoveredWindow = g.HoveredRootWindow = NULL;
|
|
|
+ g.HoveredWindow = g.HoveredRootWindow = g.HoveredWindowUnderMovingWindow = NULL;
|
|
|
g.ActiveIdWindow = g.ActiveIdPreviousFrameWindow = NULL;
|
|
|
g.MovingWindow = NULL;
|
|
|
g.ColorModifiers.clear();
|
|
|
@@ -4275,6 +4275,7 @@ static void FindHoveredWindow()
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
|
|
|
ImGuiWindow* hovered_window = NULL;
|
|
|
+ ImGuiWindow* hovered_window_ignoring_moving_window = NULL;
|
|
|
if (g.MovingWindow && !(g.MovingWindow->Flags & ImGuiWindowFlags_NoMouseInputs))
|
|
|
hovered_window = g.MovingWindow;
|
|
|
|
|
|
@@ -4297,16 +4298,27 @@ static void FindHoveredWindow()
|
|
|
if (!bb.Contains(g.IO.MousePos))
|
|
|
continue;
|
|
|
|
|
|
- // Those seemingly unnecessary extra tests are because the code here is a little different in viewport/docking branches.
|
|
|
+ // Support for one rectangular hole in any given window
|
|
|
+ // FIXME: Consider generalizing hit-testing override (with more generic data, callback, etc.) (#1512)
|
|
|
+ if (window->HitTestHoleSize.x != 0)
|
|
|
+ {
|
|
|
+ ImVec2 hole_pos(window->Pos.x + (float)window->HitTestHoleOffset.x, window->Pos.y + (float)window->HitTestHoleOffset.y);
|
|
|
+ ImVec2 hole_size((float)window->HitTestHoleSize.x, (float)window->HitTestHoleSize.y);
|
|
|
+ if (ImRect(hole_pos, hole_pos + hole_size).Contains(g.IO.MousePos))
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
if (hovered_window == NULL)
|
|
|
hovered_window = window;
|
|
|
- if (hovered_window)
|
|
|
+ if (hovered_window_ignoring_moving_window == NULL && (!g.MovingWindow || window->RootWindow != g.MovingWindow->RootWindow))
|
|
|
+ hovered_window_ignoring_moving_window = window;
|
|
|
+ if (hovered_window && hovered_window_ignoring_moving_window)
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
g.HoveredWindow = hovered_window;
|
|
|
g.HoveredRootWindow = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL;
|
|
|
-
|
|
|
+ g.HoveredWindowUnderMovingWindow = hovered_window_ignoring_moving_window;
|
|
|
}
|
|
|
|
|
|
// Test if mouse cursor is hovering given rectangle
|
|
|
@@ -5582,6 +5594,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f)
|
|
|
window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f);
|
|
|
|
|
|
+ // Lock menu offset so size calculation can use it as menu-bar windows need a minimum size.
|
|
|
+ window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x);
|
|
|
+ window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y;
|
|
|
+
|
|
|
// Collapse window by double-clicking on title bar
|
|
|
// At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing
|
|
|
if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse))
|
|
|
@@ -5904,8 +5920,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
window->DC.NavHasScroll = (window->ScrollMax.y > 0.0f);
|
|
|
|
|
|
window->DC.MenuBarAppending = false;
|
|
|
- window->DC.MenuBarOffset.x = ImMax(ImMax(window->WindowPadding.x, style.ItemSpacing.x), g.NextWindowData.MenuBarOffsetMinVal.x);
|
|
|
- window->DC.MenuBarOffset.y = g.NextWindowData.MenuBarOffsetMinVal.y;
|
|
|
window->DC.MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user);
|
|
|
window->DC.TreeDepth = 0;
|
|
|
window->DC.TreeJumpToParentOnPopMask = 0x00;
|
|
|
@@ -5942,6 +5956,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
|
|
if (!(flags & ImGuiWindowFlags_NoTitleBar))
|
|
|
RenderWindowTitleBarContents(window, title_bar_rect, name, p_open);
|
|
|
|
|
|
+ // Clear hit test shape every frame
|
|
|
+ window->HitTestHoleSize.x = window->HitTestHoleSize.y = 0;
|
|
|
+
|
|
|
// Pressing CTRL+C while holding on a window copy its content to the clipboard
|
|
|
// This works but 1. doesn't handle multiple Begin/End pairs, 2. recursing into another Begin/End pair - so we need to work that out and add better logging scope.
|
|
|
// Maybe we can support CTRL+C on every element?
|
|
|
@@ -6431,6 +6448,13 @@ void ImGui::SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond co
|
|
|
window->Collapsed = collapsed;
|
|
|
}
|
|
|
|
|
|
+void ImGui::SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size)
|
|
|
+{
|
|
|
+ IM_ASSERT(window->HitTestHoleSize.x == 0); // We don't support multiple holes/hit test filters
|
|
|
+ window->HitTestHoleSize = ImVec2ih(size);
|
|
|
+ window->HitTestHoleOffset = ImVec2ih(pos - window->Pos);
|
|
|
+}
|
|
|
+
|
|
|
void ImGui::SetWindowCollapsed(bool collapsed, ImGuiCond cond)
|
|
|
{
|
|
|
SetWindowCollapsed(GImGui->CurrentWindow, collapsed, cond);
|
|
|
@@ -7606,7 +7630,7 @@ void ImGui::OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags)
|
|
|
popup_ref.OpenPopupPos = NavCalcPreferredRefPos();
|
|
|
popup_ref.OpenMousePos = IsMousePosValid(&g.IO.MousePos) ? g.IO.MousePos : popup_ref.OpenPopupPos;
|
|
|
|
|
|
- //IMGUI_DEBUG_LOG("OpenPopupEx(0x%08X)\n", g.FrameCount, id);
|
|
|
+ IMGUI_DEBUG_LOG_POPUP("OpenPopupEx(0x%08X)\n", id);
|
|
|
if (g.OpenPopupStack.Size < current_stack_size + 1)
|
|
|
{
|
|
|
g.OpenPopupStack.push_back(popup_ref);
|
|
|
@@ -7667,7 +7691,7 @@ void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to
|
|
|
}
|
|
|
if (popup_count_to_keep < g.OpenPopupStack.Size) // This test is not required but it allows to set a convenient breakpoint on the statement below
|
|
|
{
|
|
|
- //IMGUI_DEBUG_LOG("ClosePopupsOverWindow(%s) -> ClosePopupToLevel(%d)\n", ref_window->Name, popup_count_to_keep);
|
|
|
+ IMGUI_DEBUG_LOG_POPUP("ClosePopupsOverWindow(\"%s\") -> ClosePopupToLevel(%d)\n", ref_window->Name, popup_count_to_keep);
|
|
|
ClosePopupToLevel(popup_count_to_keep, restore_focus_to_window_under_popup);
|
|
|
}
|
|
|
}
|
|
|
@@ -7675,6 +7699,7 @@ void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to
|
|
|
void ImGui::ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup)
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
+ IMGUI_DEBUG_LOG_POPUP("ClosePopupToLevel(%d), restore_focus_to_window_under_popup=%d\n", remaining, restore_focus_to_window_under_popup);
|
|
|
IM_ASSERT(remaining >= 0 && remaining < g.OpenPopupStack.Size);
|
|
|
|
|
|
// Trim open popup stack
|
|
|
@@ -7719,7 +7744,7 @@ void ImGui::CloseCurrentPopup()
|
|
|
break;
|
|
|
popup_idx--;
|
|
|
}
|
|
|
- //IMGUI_DEBUG_LOG("CloseCurrentPopup %d -> %d\n", g.BeginPopupStack.Size - 1, popup_idx);
|
|
|
+ IMGUI_DEBUG_LOG_POPUP("CloseCurrentPopup %d -> %d\n", g.BeginPopupStack.Size - 1, popup_idx);
|
|
|
ClosePopupToLevel(popup_idx, true);
|
|
|
|
|
|
// A common pattern is to close a popup when selecting a menu item/selectable that will open another window.
|
|
|
@@ -8304,18 +8329,20 @@ void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags mov
|
|
|
// This way we could find the last focused window among our children. It would be much less confusing this way?
|
|
|
static void ImGui::NavSaveLastChildNavWindowIntoParent(ImGuiWindow* nav_window)
|
|
|
{
|
|
|
- ImGuiWindow* parent_window = nav_window;
|
|
|
- while (parent_window && (parent_window->Flags & ImGuiWindowFlags_ChildWindow) != 0 && (parent_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
|
|
|
- parent_window = parent_window->ParentWindow;
|
|
|
- if (parent_window && parent_window != nav_window)
|
|
|
- parent_window->NavLastChildNavWindow = nav_window;
|
|
|
+ ImGuiWindow* parent = nav_window;
|
|
|
+ while (parent && (parent->Flags & ImGuiWindowFlags_ChildWindow) != 0 && (parent->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0)
|
|
|
+ parent = parent->ParentWindow;
|
|
|
+ if (parent && parent != nav_window)
|
|
|
+ parent->NavLastChildNavWindow = nav_window;
|
|
|
}
|
|
|
|
|
|
// Restore the last focused child.
|
|
|
// Call when we are expected to land on the Main Layer (0) after FocusWindow()
|
|
|
static ImGuiWindow* ImGui::NavRestoreLastChildNavWindow(ImGuiWindow* window)
|
|
|
{
|
|
|
- return window->NavLastChildNavWindow ? window->NavLastChildNavWindow : window;
|
|
|
+ if (window->NavLastChildNavWindow && window->NavLastChildNavWindow->WasActive)
|
|
|
+ return window->NavLastChildNavWindow;
|
|
|
+ return window;
|
|
|
}
|
|
|
|
|
|
static void NavRestoreLayer(ImGuiNavLayer layer)
|
|
|
@@ -9121,6 +9148,7 @@ void ImGui::NavUpdateWindowingOverlay()
|
|
|
PopStyleVar();
|
|
|
}
|
|
|
|
|
|
+
|
|
|
//-----------------------------------------------------------------------------
|
|
|
// [SECTION] DRAG AND DROP
|
|
|
//-----------------------------------------------------------------------------
|
|
|
@@ -9310,7 +9338,8 @@ bool ImGui::BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id)
|
|
|
return false;
|
|
|
|
|
|
ImGuiWindow* window = g.CurrentWindow;
|
|
|
- if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow)
|
|
|
+ ImGuiWindow* hovered_window = g.HoveredWindowUnderMovingWindow;
|
|
|
+ if (hovered_window == NULL || window->RootWindow != hovered_window->RootWindow)
|
|
|
return false;
|
|
|
IM_ASSERT(id != 0);
|
|
|
if (!IsMouseHoveringRect(bb.Min, bb.Max) || (id == g.DragDropPayload.SourceId))
|
|
|
@@ -9338,7 +9367,8 @@ bool ImGui::BeginDragDropTarget()
|
|
|
ImGuiWindow* window = g.CurrentWindow;
|
|
|
if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect))
|
|
|
return false;
|
|
|
- if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow)
|
|
|
+ ImGuiWindow* hovered_window = g.HoveredWindowUnderMovingWindow;
|
|
|
+ if (hovered_window == NULL || window->RootWindow != hovered_window->RootWindow)
|
|
|
return false;
|
|
|
|
|
|
const ImRect& display_rect = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ? window->DC.LastItemDisplayRect : window->DC.LastItemRect;
|
|
|
@@ -9633,6 +9663,7 @@ void ImGui::LogButtons()
|
|
|
LogToClipboard();
|
|
|
}
|
|
|
|
|
|
+
|
|
|
//-----------------------------------------------------------------------------
|
|
|
// [SECTION] SETTINGS
|
|
|
//-----------------------------------------------------------------------------
|
|
|
@@ -9887,9 +9918,9 @@ static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*,
|
|
|
ImGuiWindowSettings* settings = (ImGuiWindowSettings*)entry;
|
|
|
int x, y;
|
|
|
int i;
|
|
|
- if (sscanf(line, "Pos=%i,%i", &x, &y) == 2) settings->Pos = ImVec2ih((short)x, (short)y);
|
|
|
- else if (sscanf(line, "Size=%i,%i", &x, &y) == 2) settings->Size = ImVec2ih((short)x, (short)y);
|
|
|
- else if (sscanf(line, "Collapsed=%d", &i) == 1) settings->Collapsed = (i != 0);
|
|
|
+ if (sscanf(line, "Pos=%i,%i", &x, &y) == 2) { settings->Pos = ImVec2ih((short)x, (short)y); }
|
|
|
+ else if (sscanf(line, "Size=%i,%i", &x, &y) == 2) { settings->Size = ImVec2ih((short)x, (short)y); }
|
|
|
+ else if (sscanf(line, "Collapsed=%d", &i) == 1) { settings->Collapsed = (i != 0); }
|
|
|
}
|
|
|
|
|
|
// Apply to existing windows (if any)
|
|
|
@@ -10496,7 +10527,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
|
|
|
|
// Details for Docking
|
|
|
#ifdef IMGUI_HAS_DOCK
|
|
|
- if (ImGui::TreeNode("Docking"))
|
|
|
+ if (ImGui::TreeNode("Dock nodes"))
|
|
|
{
|
|
|
ImGui::TreePop();
|
|
|
}
|
|
|
@@ -10508,6 +10539,9 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
|
if (ImGui::SmallButton("Clear"))
|
|
|
ImGui::ClearIniSettings();
|
|
|
ImGui::SameLine();
|
|
|
+ if (ImGui::SmallButton("Save to memory"))
|
|
|
+ ImGui::SaveIniSettingsToMemory();
|
|
|
+ ImGui::SameLine();
|
|
|
if (ImGui::SmallButton("Save to disk"))
|
|
|
ImGui::SaveIniSettingsToDisk(g.IO.IniFilename);
|
|
|
ImGui::SameLine();
|
|
|
@@ -10519,7 +10553,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
|
if (ImGui::TreeNode("SettingsHandlers", "Settings handlers: (%d)", g.SettingsHandlers.Size))
|
|
|
{
|
|
|
for (int n = 0; n < g.SettingsHandlers.Size; n++)
|
|
|
- ImGui::TextUnformatted(g.SettingsHandlers[n].TypeName);
|
|
|
+ ImGui::BulletText("%s", g.SettingsHandlers[n].TypeName);
|
|
|
ImGui::TreePop();
|
|
|
}
|
|
|
if (ImGui::TreeNode("SettingsWindows", "Settings packed data: Windows: %d bytes", g.SettingsWindows.size()))
|
|
|
@@ -10556,6 +10590,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
|
|
const char* input_source_names[] = { "None", "Mouse", "Nav", "NavKeyboard", "NavGamepad" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT);
|
|
|
ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL");
|
|
|
ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL");
|
|
|
+ ImGui::Text("HoveredWindowUnderMovingWindow: '%s'", g.HoveredWindowUnderMovingWindow ? g.HoveredWindowUnderMovingWindow->Name : "NULL");
|
|
|
ImGui::Text("HoveredId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not
|
|
|
ImGui::Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, input_source_names[g.ActiveIdSource]);
|
|
|
ImGui::Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL");
|