Internals: Backport HoveredWindowUnderMovingWindow code from Docking branch.
(effectively allowing a window to be a drag payload without have to make it _NoInputs)
diff --git a/imgui.cpp b/imgui.cpp
index a74e96a..28c975e 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -3593,15 +3593,14 @@
// - 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;
@@ -3621,7 +3620,7 @@
// 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)
@@ -3935,7 +3934,7 @@
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();
@@ -4274,6 +4273,7 @@
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;
@@ -4306,16 +4306,17 @@
continue;
}
- // Those seemingly unnecessary extra tests are because the code here is a little different in viewport/docking branches.
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
@@ -9145,6 +9146,7 @@
PopStyleVar();
}
+
//-----------------------------------------------------------------------------
// [SECTION] DRAG AND DROP
//-----------------------------------------------------------------------------
@@ -9334,7 +9336,8 @@
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))
@@ -9362,7 +9365,8 @@
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;
@@ -10584,6 +10588,7 @@
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");
diff --git a/imgui_internal.h b/imgui_internal.h
index e5d72c7..317288a 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1136,6 +1136,7 @@
ImGuiWindow* CurrentWindow; // Window being drawn into
ImGuiWindow* HoveredWindow; // Will catch mouse inputs
ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only)
+ ImGuiWindow* HoveredWindowUnderMovingWindow; // Hovered window ignoring MovingWindow. Only set if MovingWindow is set.
ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actually window that is moved is generally MovingWindow->RootWindow.
ImGuiWindow* WheelingWindow; // Track the window we started mouse-wheeling on. Until a timer elapse or mouse has moved, generally keep scrolling the same window even if during the course of scrolling the mouse ends up hovering a child window.
ImVec2 WheelingWindowRefMousePos;
@@ -1342,6 +1343,7 @@
CurrentWindow = NULL;
HoveredWindow = NULL;
HoveredRootWindow = NULL;
+ HoveredWindowUnderMovingWindow = NULL;
MovingWindow = NULL;
WheelingWindow = NULL;
WheelingWindowTimer = 0.0f;