From 5dd1e38b7a5a6ed6c6d94c54c6eb54ba3a88ed81 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Fri, 9 Jul 2021 19:45:30 +0200 Subject: [PATCH] Disabled: disabled items set HoveredId, allowing e.g. HoveredIdTimer to function. (#211, #3419) + Menus: fix hovering a disabled menu or menu item not closing other menus. Rework of https://github.com/rokups/imgui/commit/c24b470 Note that the declared intent of that commit "Prevents window from being dragged if mouse hovers a disabled item." was already fullfilled by a876ad87. Changes in ButtonBehavior() not needed anymore since ImGuiButtonFlags_Disabled is gone --- docs/CHANGELOG.txt | 5 +++++ imgui.cpp | 12 ++++++++++-- imgui_widgets.cpp | 16 +++++++++------- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 0a670e6e..696e4dbc 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -39,6 +39,9 @@ Breaking Changes: - Backends: SDL2: removed unnecessary SDL_Window* parameter from ImGui_ImplSDL2_NewFrame(). (#3244) [@funchal] Kept inline redirection function (will obsolete). +- Internals: (for custom widgets): because disabled items now sets HoveredId, if you want custom widgets to + not react as hovered when disabled, in the majority of use cases it is preferable to check the "hovered" + return value of ButtonBehavior() rather than (HoveredId == id). Other Changes: - Windows: ImGuiWindowFlags_UnsavedDocument/ImGuiTabItmeFlags_UnsavedDocument display a dot instead of a '*' so it @@ -55,7 +58,9 @@ Other Changes: - InputInt/InputFloat: When used with Steps values and _ReadOnly flag, the step button look disabled. (#211) - Drag and Drop: drop target highlight doesn't try to bypass host clipping rectangle. (#4281, #3272) - Menus: MenuItem() and BeginMenu() are not affected/overlapping when style.SelectableTextAlign is altered. +- Menus: fix hovering a disabled menu or menu item not closing other menus. (#211) - Nav: Disabled items are not candidate for default focus. (#211, #787) +- Disabled: disabled items set HoveredId, allowing e.g. HoveredIdTimer to function. (#211, #3419) [@rokups] - Disabled: disabled mode more consistently release active id if the active item got disabled. (#211) - Disabled: disabled mode doesn't prevent Selectable() from looking selected. (#211) - Fixed printf-style format checks on non-MinGW flavors. (#4183, #3592) diff --git a/imgui.cpp b/imgui.cpp index 679e36af..80fb4bca 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3216,7 +3216,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id) return false; if (g.NavDisableMouseHover) return false; - if (!IsWindowContentHoverable(window, ImGuiHoveredFlags_None) || (g.CurrentItemFlags & ImGuiItemFlags_Disabled)) + if (!IsWindowContentHoverable(window, ImGuiHoveredFlags_None)) { g.HoveredIdDisabled = true; return false; @@ -3225,9 +3225,17 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id) // We exceptionally allow this function to be called with id==0 to allow using it for easy high-level // hover test in widgets code. We could also decide to split this function is two. if (id != 0) - { SetHoveredID(id); + // When disabled we'll return false but still set HoveredId + if (g.CurrentItemFlags & ImGuiItemFlags_Disabled) + { + g.HoveredIdDisabled = true; + return false; + } + + if (id != 0) + { // [DEBUG] Item Picker tool! // We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making // the cost of this tool near-zero. We can get slightly better call-stack and support picking non-hovered diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index c6f60e8b..48a01ea8 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1445,7 +1445,7 @@ bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float if (g.ActiveId != id) SetItemAllowOverlap(); - if (held || (g.HoveredId == id && g.HoveredIdPreviousFrame == id && g.HoveredIdTimer >= hover_visibility_delay)) + if (held || (hovered && g.HoveredIdPreviousFrame == id && g.HoveredIdTimer >= hover_visibility_delay)) SetMouseCursor(axis == ImGuiAxis_Y ? ImGuiMouseCursor_ResizeNS : ImGuiMouseCursor_ResizeEW); ImRect bb_render = bb; @@ -2431,7 +2431,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data, } // Draw frame - const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); + const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); @@ -3037,7 +3037,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat } // Draw frame - const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); + const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding); @@ -3185,7 +3185,7 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d } // Draw frame - const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); + const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, g.Style.FrameRounding); @@ -7964,7 +7964,6 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); if (pressed && !is_tab_button) tab_bar->NextSelectedTabId = id; - hovered |= (g.HoveredId == id); // Allow the close button to overlap unless we are dragging (in which case we don't want any overlapping tabs to be hovered) if (g.ActiveId != id) @@ -8028,8 +8027,11 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, PopClipRect(); window->DC.CursorPos = backup_main_cursor_pos; - // Tooltip (FIXME: Won't work over the close button because ItemOverlap systems messes up with HoveredIdTimer) - // We test IsItemHovered() to discard e.g. when another item is active or drag and drop over the tab bar (which g.HoveredId ignores) + // Tooltip + // (Won't work over the close button because ItemOverlap systems messes up with HoveredIdTimer-> seems ok) + // (We test IsItemHovered() to discard e.g. when another item is active or drag and drop over the tab bar, which g.HoveredId ignores) + // FIXME: This is a mess. + // FIXME: We may want disabled tab to still display the tooltip? if (text_clipped && g.HoveredId == id && !held && g.HoveredIdNotActiveTimer > g.TooltipSlowDelay && IsItemHovered()) if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip) && !(tab->Flags & ImGuiTabItemFlags_NoTooltip)) SetTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label);