diff --git a/imgui.cpp b/imgui.cpp index cfd85bb7b..a476e8752 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -930,7 +930,8 @@ struct ImGuiDrawContext int TreeDepth; ImGuiID LastItemID; ImRect LastItemRect; - bool LastItemHovered; + bool LastItemHoveredAndUsable; + bool LastItemHoveredRectOnly; ImVector ChildWindows; ImVector AllowKeyboardFocus; ImVector ItemWidth; // 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window @@ -959,7 +960,7 @@ struct ImGuiDrawContext TreeDepth = 0; LastItemID = 0; LastItemRect = ImRect(0.0f,0.0f,0.0f,0.0f); - LastItemHovered = false; + LastItemHoveredAndUsable = LastItemHoveredRectOnly = false; StateStorage = NULL; ColumnsStartX = 0.0f; @@ -1150,6 +1151,7 @@ struct ImGuiWindow ImVec2 Size; // Current size (==SizeFull or collapsed title bar size) ImVec2 SizeFull; // Size when non collapsed ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame + ImGuiID MoveID; // == window->GetID("#MOVE") float ScrollY; float NextScrollY; bool ScrollbarY; @@ -1487,6 +1489,7 @@ ImGuiWindow::ImGuiWindow(const char* name) Name = ImStrdup(name); ID = ImHash(name, 0); IDStack.push_back(ID); + MoveID = GetID("#MOVE"); Flags = 0; PosFloat = Pos = ImVec2(0.0f, 0.0f); @@ -2057,7 +2060,7 @@ void ImGui::Render() { IM_ASSERT(g.MovedWindow == NULL); g.MovedWindow = g.HoveredWindow; - SetActiveId(g.HoveredRootWindow->GetID("#MOVE")); + SetActiveId(g.HoveredRootWindow->MoveID); } // Sort the window list so that all child windows are after their parent @@ -2531,7 +2534,13 @@ ImVec2 ImGui::GetMousePos() bool ImGui::IsItemHovered() { ImGuiWindow* window = GetCurrentWindow(); - return window->DC.LastItemHovered; + return window->DC.LastItemHoveredAndUsable; +} + +bool ImGui::IsItemHoveredRectOnly() +{ + ImGuiWindow* window = GetCurrentWindow(); + return window->DC.LastItemHoveredRectOnly; } bool ImGui::IsItemActive() @@ -2882,9 +2891,8 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size, float bg window->IDStack.resize(1); // Move window (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows. - const ImGuiID move_id = window->GetID("#MOVE"); - RegisterAliveId(move_id); - if (g.ActiveId == move_id) + RegisterAliveId(window->MoveID); + if (g.ActiveId == window->MoveID) { if (g.IO.MouseDown[0]) { @@ -6786,14 +6794,27 @@ static bool ItemAdd(const ImRect& bb, const ImGuiID* id) window->DC.LastItemRect = bb; if (IsClipped(bb)) { - window->DC.LastItemHovered = false; + window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRectOnly = false; return false; } // This is a sensible default, but widgets are free to override it after calling ItemAdd() - const bool hovered = IsMouseHoveringRect(bb); - //const bool hovered = (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdIsFocusedOnly) && IsMouseHoveringRect(bb); // matching the behavior of IsHovered(), not always what the user wants? - window->DC.LastItemHovered = hovered; + ImGuiState& g = *GImGui; + if (IsMouseHoveringRect(bb)) + { + // Matching the behavior of IsHovered() but ignore if ActiveId==window->MoveID (we clicked on the window background) + // So that clicking on items with no active id such as Text() still returns true with IsItemHovered() + window->DC.LastItemHoveredRectOnly = true; + if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdIsFocusedOnly || (g.ActiveId == window->MoveID)) + window->DC.LastItemHoveredAndUsable = true; + else + window->DC.LastItemHoveredAndUsable = false; + } + else + { + window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRectOnly = false; + } + return true; } diff --git a/imgui.h b/imgui.h index cfbf32048..ec0846b3e 100644 --- a/imgui.h +++ b/imgui.h @@ -352,6 +352,7 @@ namespace ImGui // Utilities IMGUI_API bool IsItemHovered(); // was the last item hovered by mouse? + IMGUI_API bool IsItemHoveredRectOnly(); // was the last item hovered by mouse? even if another item is active while we are hovering this. IMGUI_API bool IsItemActive(); // was the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false) IMGUI_API bool IsAnyItemActive(); // IMGUI_API ImVec2 GetItemActiveDragDelta(); // mouse delta from the time the item first got active