Skip to content

Commit ee643b2

Browse files
committed
IsItemHovered(): fixed return value false positive when used after EndChild(), EndGroup() or widgets using either... (ocornut#3851, ocornut#1370)
...when the hovered location is located within a child window, e.g. InputTextMultiline(). This is intended to have no side effects, but brace yourself for the possible comeback.. This essentially makes IsItemHovered() not accept hover from child windows, but EndChild/EndGroup are forwarded. More or less should fix/revert c76f014 which was a revert of 344d48b
1 parent b53b8f5 commit ee643b2

File tree

3 files changed

+26
-11
lines changed

3 files changed

+26
-11
lines changed

Diff for: docs/CHANGELOG.txt

+3
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ Other Changes:
5252
area (e.g. when window is collapsed + moved in a corner) to facilitate moving the window away. (#3825)
5353
- Window, Nav: Fixed crash when calling SetWindowFocus(NULL) as the time a new window appears. (#3865) [@nem0]
5454
- Tables: Fixed unaligned accesses when using TableSetBgColor(ImGuiTableBgTarget_CellBg). (#3872)
55+
- IsItemHovered(): fixed return value false positive when used after EndChild(), EndGroup() or widgets using
56+
either of them, when the hovered location is located within a child window, e.g. InputTextMultiline().
57+
This is intended to have no side effects, but brace yourself for the possible comeback.. (#3851, #1370)
5558
- Added GetAllocatorFunctions() to facilitate sharing allocators accross DLL boundaries. (#3836)
5659
- ImFontAtlas: Added 'bool TexPixelsUseColors' output to help backend decide of underlying texture format. (#3369)
5760
This can currently only ever be set by the Freetype renderer.

Diff for: imgui.cpp

+18-8
Original file line numberDiff line numberDiff line change
@@ -3122,20 +3122,22 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
31223122
return IsItemFocused();
31233123

31243124
// Test for bounding box overlap, as updated as ItemAdd()
3125-
if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect))
3125+
ImGuiItemStatusFlags status_flags = window->DC.LastItemStatusFlags;
3126+
if (!(status_flags & ImGuiItemStatusFlags_HoveredRect))
31263127
return false;
31273128
IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0); // Flags not supported by this function
31283129

31293130
// Test if we are hovering the right window (our window could be behind another window)
3130-
// [2017/10/16] Reverted commit 344d48be3 and testing RootWindow instead. I believe it is correct to NOT test for RootWindow but this leaves us unable to use IsItemHovered() after EndChild() itself.
3131-
// Until a solution is found I believe reverting to the test from 2017/09/27 is safe since this was the test that has been running for a long while.
3132-
//if (g.HoveredWindow != window)
3133-
// return false;
3134-
if (g.HoveredRootWindow != window->RootWindow && !(flags & ImGuiHoveredFlags_AllowWhenOverlapped))
3135-
return false;
3131+
// [2021/03/02] Reworked / reverted the revert, finally. Note we want e.g. BeginGroup/ItemAdd/EndGroup to work as well. (#3851)
3132+
// [2017/10/16] Reverted commit 344d48be3 and testing RootWindow instead. I believe it is correct to NOT test for RootWindow but this leaves us unable
3133+
// to use IsItemHovered() after EndChild() itself. Until a solution is found I believe reverting to the test from 2017/09/27 is safe since this was
3134+
// the test that has been running for a long while.
3135+
if (g.HoveredWindow != window && (status_flags & ImGuiItemStatusFlags_HoveredWindow) == 0)
3136+
if ((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0)
3137+
return false;
31363138

31373139
// Test if another item is active (e.g. being dragged)
3138-
if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
3140+
if ((flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem) == 0)
31393141
if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId)
31403142
return false;
31413143

@@ -5014,6 +5016,8 @@ void ImGui::EndChild()
50145016
// Not navigable into
50155017
ItemAdd(bb, 0);
50165018
}
5019+
if (g.HoveredWindow == window)
5020+
parent_window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
50175021
}
50185022
g.WithinEndChild = false;
50195023
g.LogLinePosY = -FLT_MAX; // To enforce a carriage return
@@ -7647,6 +7651,7 @@ void ImGui::BeginGroup()
76477651
group_data.BackupCurrLineSize = window->DC.CurrLineSize;
76487652
group_data.BackupCurrLineTextBaseOffset = window->DC.CurrLineTextBaseOffset;
76497653
group_data.BackupActiveIdIsAlive = g.ActiveIdIsAlive;
7654+
group_data.BackupHoveredIdIsAlive = g.HoveredId != 0;
76507655
group_data.BackupActiveIdPreviousFrameIsAlive = g.ActiveIdPreviousFrameIsAlive;
76517656
group_data.EmitItem = true;
76527657

@@ -7700,6 +7705,11 @@ void ImGui::EndGroup()
77007705
window->DC.LastItemId = g.ActiveIdPreviousFrame;
77017706
window->DC.LastItemRect = group_bb;
77027707

7708+
// Forward Hovered flag
7709+
const bool group_contains_curr_hovered_id = (group_data.BackupHoveredIdIsAlive == false) && g.HoveredId != 0;
7710+
if (group_contains_curr_hovered_id)
7711+
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredWindow;
7712+
77037713
// Forward Edited flag
77047714
if (group_contains_curr_active_id && g.ActiveIdHasBeenEditedThisFrame)
77057715
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_Edited;

Diff for: imgui_internal.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -697,12 +697,13 @@ enum ImGuiItemStatusFlags_
697697
{
698698
ImGuiItemStatusFlags_None = 0,
699699
ImGuiItemStatusFlags_HoveredRect = 1 << 0,
700-
ImGuiItemStatusFlags_HasDisplayRect = 1 << 1,
700+
ImGuiItemStatusFlags_HasDisplayRect = 1 << 1, // LastItemDisplayRect is valid
701701
ImGuiItemStatusFlags_Edited = 1 << 2, // Value exposed by item was edited in the current frame (should match the bool return value of most widgets)
702702
ImGuiItemStatusFlags_ToggledSelection = 1 << 3, // Set when Selectable(), TreeNode() reports toggling a selection. We can't report "Selected" because reporting the change allows us to handle clipping with less issues.
703703
ImGuiItemStatusFlags_ToggledOpen = 1 << 4, // Set when TreeNode() reports toggling their open state.
704704
ImGuiItemStatusFlags_HasDeactivated = 1 << 5, // Set if the widget/group is able to provide data for the ImGuiItemStatusFlags_Deactivated flag.
705-
ImGuiItemStatusFlags_Deactivated = 1 << 6 // Only valid if ImGuiItemStatusFlags_HasDeactivated is set.
705+
ImGuiItemStatusFlags_Deactivated = 1 << 6, // Only valid if ImGuiItemStatusFlags_HasDeactivated is set.
706+
ImGuiItemStatusFlags_HoveredWindow = 1 << 7 // Override the HoveredWindow test to allow cross-window hover testing.
706707

707708
#ifdef IMGUI_ENABLE_TEST_ENGINE
708709
, // [imgui_tests only]
@@ -924,7 +925,7 @@ struct ImGuiStyleMod
924925
};
925926

926927
// Stacked storage data for BeginGroup()/EndGroup()
927-
struct ImGuiGroupData
928+
struct IMGUI_API ImGuiGroupData
928929
{
929930
ImGuiID WindowID;
930931
ImVec2 BackupCursorPos;
@@ -935,6 +936,7 @@ struct ImGuiGroupData
935936
float BackupCurrLineTextBaseOffset;
936937
ImGuiID BackupActiveIdIsAlive;
937938
bool BackupActiveIdPreviousFrameIsAlive;
939+
bool BackupHoveredIdIsAlive;
938940
bool EmitItem;
939941
};
940942

0 commit comments

Comments
 (0)