mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-11-04 07:01:04 +01:00 
			
		
		
		
	IsItemHovered(), IsWindowHovered(): added flags to enable various and more specific behavior. Will enable improvements for popups/context menus and drag'n drop. (relate ~#439, #1013, #143, #925)
The legacy confusing IsItemRectHovered(), IsWindowRectHovered() can be completely removed now. Changed IsWindowHovered() behavior with default parameter: it now return false is the window is blocked by a popup. Demo: Added tests for those two functions.
This commit is contained in:
		
							
								
								
									
										51
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								imgui.cpp
									
									
									
									
									
								
							@@ -216,11 +216,12 @@
 | 
			
		||||
 Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
 | 
			
		||||
 Also read releases logs https://github.com/ocornut/imgui/releases for more details.
 | 
			
		||||
 | 
			
		||||
 - 2017/10/20 (1.52) - removed the IsItemRectHovered()/IsWindowRectHovered() names introduced in 1.51, the new flags available for IsItemHovered() and IsWindowHovered() are providing much more details/options, and those legacy entry points were confusing/misleading.
 | 
			
		||||
 - 2017/10/17 (1.52) - marked the old 5-parameters version of Begin() as obsolete (still available). Use SetNextWindowSize()+Begin() instead!
 | 
			
		||||
 - 2017/10/11 (1.52) - renamed AlignFirstTextHeightToWidgets() to AlignTextToFramePadding(). Kept inline redirection function (will obsolete).
 | 
			
		||||
 - 2017/09/25 (1.52) - removed SetNextWindowPosCenter() because SetNextWindowPos() now has the optional pivot information to do the same and more. Kept redirection function (will obsolete). 
 | 
			
		||||
 - 2017/08/25 (1.52) - io.MousePos needs to be set to ImVec2(-FLT_MAX,-FLT_MAX) when mouse is unavailable/missing. Previously ImVec2(-1,-1) was enough but we now accept negative mouse coordinates. In your binding if you need to support unavailable mouse, make sure to replace "io.MousePos = ImVec2(-1,-1)" with "io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX)".
 | 
			
		||||
 - 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete).
 | 
			
		||||
 - 2017/08/22 (1.51) - renamed IsItemHoveredRect() to IsItemRectHovered(). Kept inline redirection function (will obsolete). -> (1.52) use IsItemHovered(ImGuiHoveredFlags_RectOnly)! 
 | 
			
		||||
                     - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete).
 | 
			
		||||
                     - renamed IsMouseHoveringWindow() to IsWindowRectHovered() for consistency. Kept inline redirection function (will obsolete).
 | 
			
		||||
 - 2017/08/20 (1.51) - renamed GetStyleColName() to GetStyleColorName() for consistency.
 | 
			
		||||
@@ -1944,15 +1945,22 @@ void ImGui::KeepAliveID(ImGuiID id)
 | 
			
		||||
        g.ActiveIdIsAlive = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline bool IsWindowContentHoverable(ImGuiWindow* window)
 | 
			
		||||
static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
 | 
			
		||||
{
 | 
			
		||||
    // An active popup disable hovering on other windows (apart from its own children)
 | 
			
		||||
    // FIXME-OPT: This could be cached/stored within the window.
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    if (g.NavWindow)
 | 
			
		||||
        if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow)
 | 
			
		||||
            if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) != 0 && focused_root_window->WasActive && focused_root_window != window->RootWindow)
 | 
			
		||||
                return false;
 | 
			
		||||
            if (focused_root_window->WasActive && focused_root_window != window->RootWindow)
 | 
			
		||||
            {
 | 
			
		||||
                // For the purpose of those flags we differentiate "standard popup" from "modal popup"
 | 
			
		||||
                // NB: The order of those two tests is important because Modal windows are also Popups.
 | 
			
		||||
                if (focused_root_window->Flags & ImGuiWindowFlags_Modal)
 | 
			
		||||
                    return false;
 | 
			
		||||
                if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiHoveredFlags_AllowWhenBlockedByPopup))
 | 
			
		||||
                    return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
@@ -2012,7 +2020,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id)
 | 
			
		||||
// This is roughly matching the behavior of internal-facing ItemHoverable()
 | 
			
		||||
// - we allow hovering to be true when ActiveId==window->MoveID, so that clicking on non-interactive items such as a Text() item still returns true with IsItemHovered())
 | 
			
		||||
// - this should work even for non-interactive items that have no ID, so we cannot use LastItemId
 | 
			
		||||
bool ImGui::IsItemHovered()
 | 
			
		||||
bool ImGui::IsItemHovered(ImGuiHoveredFlags flags)
 | 
			
		||||
{
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
 | 
			
		||||
@@ -2023,21 +2031,16 @@ bool ImGui::IsItemHovered()
 | 
			
		||||
    // 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.
 | 
			
		||||
    //if (g.HoveredWindow != window)
 | 
			
		||||
    //    return false;
 | 
			
		||||
    if (g.HoveredRootWindow != window->RootWindow)
 | 
			
		||||
    if (g.HoveredRootWindow != window->RootWindow && !(flags & ImGuiHoveredFlags_AllowWhenOverlapped))
 | 
			
		||||
        return false;
 | 
			
		||||
    if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId)
 | 
			
		||||
        return false;
 | 
			
		||||
    if (!IsWindowContentHoverable(window))
 | 
			
		||||
    if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem))
 | 
			
		||||
        if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId)
 | 
			
		||||
            return false;
 | 
			
		||||
    if (!IsWindowContentHoverable(window, flags))
 | 
			
		||||
        return false;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ImGui::IsItemRectHovered()
 | 
			
		||||
{
 | 
			
		||||
    ImGuiWindow* window = GetCurrentWindowRead();
 | 
			
		||||
    return window->DC.LastItemRectHoveredRect;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Internal facing ItemHoverable() used when submitting widgets. Differs slightly from IsItemHovered().
 | 
			
		||||
bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
 | 
			
		||||
{
 | 
			
		||||
@@ -2052,7 +2055,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id)
 | 
			
		||||
        return false;
 | 
			
		||||
    if (!IsMouseHoveringRect(bb.Min, bb.Max))
 | 
			
		||||
        return false;
 | 
			
		||||
    if (!IsWindowContentHoverable(window))
 | 
			
		||||
    if (!IsWindowContentHoverable(window, ImGuiHoveredFlags_Default))
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    SetHoveredID(id);
 | 
			
		||||
@@ -5086,16 +5089,11 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx)
 | 
			
		||||
    return "Unknown";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ImGui::IsWindowHovered()
 | 
			
		||||
bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags)
 | 
			
		||||
{
 | 
			
		||||
    IM_ASSERT((flags & (ImGuiHoveredFlags_AllowWhenOverlapped | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) == 0);   // Flags not supported by this function
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    return g.HoveredWindow == g.CurrentWindow && IsWindowContentHoverable(g.HoveredRootWindow);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ImGui::IsWindowRectHovered()
 | 
			
		||||
{
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    return g.HoveredWindow == g.CurrentWindow;
 | 
			
		||||
    return g.HoveredWindow == g.CurrentWindow && IsWindowContentHoverable(g.HoveredRootWindow, flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ImGui::IsWindowFocused()
 | 
			
		||||
@@ -5116,10 +5114,11 @@ bool ImGui::IsRootWindowOrAnyChildFocused()
 | 
			
		||||
    return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ImGui::IsRootWindowOrAnyChildHovered()
 | 
			
		||||
bool ImGui::IsRootWindowOrAnyChildHovered(ImGuiHoveredFlags flags)
 | 
			
		||||
{
 | 
			
		||||
    IM_ASSERT((flags & (ImGuiHoveredFlags_AllowWhenOverlapped | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) == 0);   // Flags not supported by this function
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    return g.HoveredRootWindow && (g.HoveredRootWindow == g.CurrentWindow->RootWindow) && IsWindowContentHoverable(g.HoveredRootWindow);
 | 
			
		||||
    return g.HoveredRootWindow && (g.HoveredRootWindow == g.CurrentWindow->RootWindow) && IsWindowContentHoverable(g.HoveredRootWindow, flags);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float ImGui::GetWindowWidth()
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										23
									
								
								imgui.h
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								imgui.h
									
									
									
									
									
								
							@@ -80,6 +80,7 @@ typedef int ImGuiColumnsFlags;      // flags: for *Columns*()
 | 
			
		||||
typedef int ImGuiInputTextFlags;    // flags: for InputText*()                  // enum ImGuiInputTextFlags_
 | 
			
		||||
typedef int ImGuiSelectableFlags;   // flags: for Selectable()                  // enum ImGuiSelectableFlags_
 | 
			
		||||
typedef int ImGuiTreeNodeFlags;     // flags: for TreeNode*(), Collapsing*()    // enum ImGuiTreeNodeFlags_
 | 
			
		||||
typedef int ImGuiHoveredFlags;      // flags: for IsItemHovered()               // enum ImGuiHoveredFlags_
 | 
			
		||||
typedef int (*ImGuiTextEditCallback)(ImGuiTextEditCallbackData *data);
 | 
			
		||||
typedef void (*ImGuiSizeConstraintCallback)(ImGuiSizeConstraintCallbackData* data);
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
@@ -414,8 +415,7 @@ namespace ImGui
 | 
			
		||||
    IMGUI_API void          StyleColorsClassic(ImGuiStyle* dst = NULL);
 | 
			
		||||
 | 
			
		||||
    // Utilities
 | 
			
		||||
    IMGUI_API bool          IsItemHovered();                                                    // is the last item hovered by mouse (and usable)?
 | 
			
		||||
    IMGUI_API bool          IsItemRectHovered();                                                // is the last item hovered by mouse? even if another item is active or window is blocked by popup while we are hovering this
 | 
			
		||||
    IMGUI_API bool          IsItemHovered(ImGuiHoveredFlags flags = 0);                         // is the last item hovered by mouse (and usable)?
 | 
			
		||||
    IMGUI_API bool          IsItemActive();                                                     // is 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          IsItemClicked(int mouse_button = 0);                                // is the last item clicked? (e.g. button/node just clicked on)
 | 
			
		||||
    IMGUI_API bool          IsItemVisible();                                                    // is the last item visible? (aka not out of sight due to clipping/scrolling.)
 | 
			
		||||
@@ -426,11 +426,10 @@ namespace ImGui
 | 
			
		||||
    IMGUI_API ImVec2        GetItemRectSize();                                                  // "
 | 
			
		||||
    IMGUI_API void          SetItemAllowOverlap();                                              // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area.
 | 
			
		||||
    IMGUI_API bool          IsWindowFocused();                                                  // is current window focused
 | 
			
		||||
    IMGUI_API bool          IsWindowHovered();                                                  // is current window hovered and hoverable (not blocked by a popup) (differentiate child windows from each others)
 | 
			
		||||
    IMGUI_API bool          IsWindowRectHovered();                                              // is current window rectangle hovered, disregarding of any consideration of being blocked by a popup. (unlike IsWindowHovered() this will return true even if the window is blocked because of a popup)
 | 
			
		||||
    IMGUI_API bool          IsWindowHovered(ImGuiHoveredFlags flags = 0);                       // is current window hovered (and typically: not blocked by a popup/modal)
 | 
			
		||||
    IMGUI_API bool          IsRootWindowFocused();                                              // is current root window focused (root = top-most parent of a child, otherwise self)
 | 
			
		||||
    IMGUI_API bool          IsRootWindowOrAnyChildFocused();                                    // is current root window or any of its child (including current window) focused
 | 
			
		||||
    IMGUI_API bool          IsRootWindowOrAnyChildHovered();                                    // is current root window or any of its child (including current window) hovered and hoverable (not blocked by a popup)
 | 
			
		||||
    IMGUI_API bool          IsRootWindowOrAnyChildHovered(ImGuiHoveredFlags flags = 0);         // is current root window or any of its child (including current window) hovered and hoverable (not blocked by a popup)
 | 
			
		||||
    IMGUI_API bool          IsAnyWindowHovered();                                               // is mouse hovering any visible window
 | 
			
		||||
    IMGUI_API bool          IsRectVisible(const ImVec2& size);                                  // test if rectangle (of given size, starting from cursor position) is visible / not clipped.
 | 
			
		||||
    IMGUI_API bool          IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max);      // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side.
 | 
			
		||||
@@ -569,6 +568,16 @@ enum ImGuiSelectableFlags_
 | 
			
		||||
    ImGuiSelectableFlags_AllowDoubleClick   = 1 << 2    // Generate press events on double clicks too
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum ImGuiHoveredFlags_
 | 
			
		||||
{
 | 
			
		||||
    ImGuiHoveredFlags_Default                       = 0,        // Return true if directly over the item/window, not obstructed by another window, not obstructed by an active popup or modal blocking inputs under them.
 | 
			
		||||
    ImGuiHoveredFlags_AllowWhenBlockedByPopup       = 1 << 0,   // Return true even if a popup window is normally blocking access to this item/window
 | 
			
		||||
    //ImGuiHoveredFlags_AllowWhenBlockedByModal     = 1 << 1,   // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet.
 | 
			
		||||
    ImGuiHoveredFlags_AllowWhenBlockedByActiveItem  = 1 << 2,   // Return true even if an active item is blocking access to this item/window
 | 
			
		||||
    ImGuiHoveredFlags_AllowWhenOverlapped           = 1 << 3,   // Return true even if the position is overlapped by another window
 | 
			
		||||
    ImGuiHoveredFlags_RectOnly                      = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// User fill ImGuiIO.KeyMap[] array with indices into the ImGuiIO.KeysDown[512] array
 | 
			
		||||
enum ImGuiKey_
 | 
			
		||||
{
 | 
			
		||||
@@ -881,10 +890,10 @@ namespace ImGui
 | 
			
		||||
    bool                    Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE 1.52+. use SetNextWindowSize() instead if you want to set a window size.
 | 
			
		||||
    static inline void      AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); }     // OBSOLETE 1.52+
 | 
			
		||||
    static inline void      SetNextWindowPosCenter(ImGuiCond cond = 0) { SetNextWindowPos(ImVec2(GetIO().DisplaySize.x * 0.5f, GetIO().DisplaySize.y * 0.5f), cond, ImVec2(0.5f, 0.5f)); } // OBSOLETE 1.52+
 | 
			
		||||
    static inline bool      IsItemHoveredRect() { return IsItemRectHovered(); }                // OBSOLETE 1.51+
 | 
			
		||||
    static inline bool      IsItemHoveredRect() { return IsItemHovered(ImGuiHoveredFlags_RectOnly); } // OBSOLETE 1.51+
 | 
			
		||||
    static inline bool      IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // OBSOLETE 1.51+. This was partly broken. You probably wanted to use ImGui::GetIO().WantCaptureMouse instead.
 | 
			
		||||
    static inline bool      IsMouseHoveringAnyWindow() { return IsAnyWindowHovered(); }        // OBSOLETE 1.51+
 | 
			
		||||
    static inline bool      IsMouseHoveringWindow() { return IsWindowRectHovered(); }          // OBSOLETE 1.51+
 | 
			
		||||
    static inline bool      IsMouseHoveringWindow() { return IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); } // OBSOLETE 1.51+
 | 
			
		||||
    static inline bool      CollapsingHeader(const char* label, const char* str_id, bool framed = true, bool default_open = false) { (void)str_id; (void)framed; ImGuiTreeNodeFlags default_open_flags = 1 << 5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } // OBSOLETE 1.49+
 | 
			
		||||
    static inline ImFont*   GetWindowFont() { return GetFont(); }                              // OBSOLETE 1.48+
 | 
			
		||||
    static inline float     GetWindowFontSize() { return GetFontSize(); }                      // OBSOLETE 1.48+
 | 
			
		||||
 
 | 
			
		||||
@@ -1763,6 +1763,34 @@ void ImGui::ShowTestWindow(bool* p_open)
 | 
			
		||||
            ImGui::TreePop();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (ImGui::TreeNode("Hovering"))
 | 
			
		||||
        {
 | 
			
		||||
            // Testing IsWindowHovered() function
 | 
			
		||||
            ImGui::BulletText(
 | 
			
		||||
                "IsWindowHovered() = %d\n"
 | 
			
		||||
                "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n",
 | 
			
		||||
                //"IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n",
 | 
			
		||||
                ImGui::IsWindowHovered(),
 | 
			
		||||
                ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup));
 | 
			
		||||
                //ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem));
 | 
			
		||||
 | 
			
		||||
            // Testing IsItemHovered() function (because BulletText is an item itself and that would affect the output of IsItemHovered, we pass all lines in a single items to shorten the code)
 | 
			
		||||
            ImGui::Button("ITEM");
 | 
			
		||||
            ImGui::BulletText(
 | 
			
		||||
                "IsItemHovered() = %d\n"
 | 
			
		||||
                "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n"
 | 
			
		||||
                "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n"
 | 
			
		||||
                "IsItemHovered(_AllowWhenOverlapped) = %d\n"
 | 
			
		||||
                "IsItemhovered(_RectOnly) = %d\n",
 | 
			
		||||
                ImGui::IsItemHovered(),
 | 
			
		||||
                ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
 | 
			
		||||
                ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
 | 
			
		||||
                ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped),
 | 
			
		||||
                ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly));
 | 
			
		||||
 | 
			
		||||
            ImGui::TreePop();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (ImGui::TreeNode("Dragging"))
 | 
			
		||||
        {
 | 
			
		||||
            ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user