Internals: Backport HoveredWindowUnderMovingWindow code from Docking branch.

(effectively allowing a window to be a drag payload without have to make it _NoInputs)
This commit is contained in:
omar 2020-07-29 15:26:31 +02:00
parent 218ff3a2a5
commit 76ddacd2a1
2 changed files with 19 additions and 12 deletions

View File

@ -3593,15 +3593,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;
@ -3621,7 +3620,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)
@ -3935,7 +3934,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();
@ -4274,6 +4273,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;
@ -4306,16 +4306,17 @@ static void FindHoveredWindow()
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 @@ void ImGui::NavUpdateWindowingOverlay()
PopStyleVar();
}
//-----------------------------------------------------------------------------
// [SECTION] DRAG AND DROP
//-----------------------------------------------------------------------------
@ -9334,7 +9336,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))
@ -9362,7 +9365,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;
@ -10584,6 +10588,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");

View File

@ -1136,6 +1136,7 @@ struct ImGuiContext
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 @@ struct ImGuiContext
CurrentWindow = NULL;
HoveredWindow = NULL;
HoveredRootWindow = NULL;
HoveredWindowUnderMovingWindow = NULL;
MovingWindow = NULL;
WheelingWindow = NULL;
WheelingWindowTimer = 0.0f;