Skip to content

Commit

Permalink
Internals: Backport HoveredWindowUnderMovingWindow code from Docking …
Browse files Browse the repository at this point in the history
…branch.

(effectively allowing a window to be a drag payload without have to make it _NoInputs)
  • Loading branch information
ocornut committed Jul 29, 2020
1 parent 218ff3a commit 76ddacd
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 12 deletions.
29 changes: 17 additions & 12 deletions imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -9145,6 +9146,7 @@ void ImGui::NavUpdateWindowingOverlay()
PopStyleVar();
}


//-----------------------------------------------------------------------------
// [SECTION] DRAG AND DROP
//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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");
Expand Down
2 changes: 2 additions & 0 deletions imgui_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -1342,6 +1343,7 @@ struct ImGuiContext
CurrentWindow = NULL;
HoveredWindow = NULL;
HoveredRootWindow = NULL;
HoveredWindowUnderMovingWindow = NULL;
MovingWindow = NULL;
WheelingWindow = NULL;
WheelingWindowTimer = 0.0f;
Expand Down

0 comments on commit 76ddacd

Please sign in to comment.