From 0bae2db77fdfe16f0f3c0f76b3af60de9f624b5e Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 18 Oct 2024 18:07:58 +0200 Subject: [PATCH] Internals: (Breaking) renamed NavDisableMouseHover to NavHighlightItemUnderNav. Considering adding NavHighlightItemUnderMouse as well, but would require to resolve quite a few ambiguities and for a feature we don't have yet. --- imgui.cpp | 30 +++++++++++++++--------------- imgui_internal.h | 9 +++++---- imgui_widgets.cpp | 14 +++++++------- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6679291c2..09acf5cd6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3911,7 +3911,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas) NavIdIsAlive = false; NavMousePosDirty = false; NavCursorVisible = false; - NavDisableMouseHover = false; + NavHighlightItemUnderNav = false; NavAnyRequest = false; NavInitRequest = false; @@ -4444,7 +4444,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) ImGuiWindow* window = g.CurrentWindow; IM_ASSERT_USER_ERROR((flags & ~ImGuiHoveredFlags_AllowedMaskForIsItemHovered) == 0, "Invalid flags for IsItemHovered()!"); - if (g.NavDisableMouseHover && g.NavCursorVisible && !(flags & ImGuiHoveredFlags_NoNavOverride)) + if (g.NavHighlightItemUnderNav && g.NavCursorVisible && !(flags & ImGuiHoveredFlags_NoNavOverride)) { if (!IsItemFocused()) return false; @@ -4615,7 +4615,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag } #endif - if (g.NavDisableMouseHover && (item_flags & ImGuiItemFlags_NoNavDisableMouseHover) == 0) + if (g.NavHighlightItemUnderNav && (item_flags & ImGuiItemFlags_NoNavDisableMouseHover) == 0) return false; return true; @@ -6589,7 +6589,7 @@ static int ImGui::UpdateWindowManualResize(ImGuiWindow* window, const ImVec2& si g.NavWindowingAccumDeltaSize += nav_resize_dir * resize_step; g.NavWindowingAccumDeltaSize = ImMax(g.NavWindowingAccumDeltaSize, clamp_rect.Min - window->Pos - window->Size); // We need Pos+Size >= clmap_rect.Min, so Size >= clmap_rect.Min - Pos, so size_delta >= clmap_rect.Min - window->Pos - window->Size g.NavWindowingToggleLayer = false; - g.NavDisableMouseHover = true; + g.NavHighlightItemUnderNav = true; resize_grip_col[0] = GetColorU32(ImGuiCol_ResizeGripActive); ImVec2 accum_floored = ImTrunc(g.NavWindowingAccumDeltaSize); if (accum_floored.x != 0.0f || accum_floored.y != 0.0f) @@ -7859,7 +7859,7 @@ void ImGui::FocusWindow(ImGuiWindow* window, ImGuiFocusRequestFlags flags) if (g.NavWindow != window) { SetNavWindow(window); - if (window && g.NavDisableMouseHover) + if (window && g.NavHighlightItemUnderNav) g.NavMousePosDirty = true; g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId g.NavLayer = ImGuiNavLayer_Main; @@ -9778,7 +9778,7 @@ static void ImGui::UpdateMouseInputs() // If mouse moved we re-enable mouse hovering in case it was disabled by gamepad/keyboard. In theory should use a >0.0f threshold but would need to reset in everywhere we set this to true. if (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f) - g.NavDisableMouseHover = false; + g.NavHighlightItemUnderNav = false; for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) { @@ -9817,7 +9817,7 @@ static void ImGui::UpdateMouseInputs() // Clicking any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation if (io.MouseClicked[i]) - g.NavDisableMouseHover = false; + g.NavHighlightItemUnderNav = false; } } @@ -12189,7 +12189,7 @@ ImVec2 ImGui::FindBestWindowPosForPopup(ImGuiWindow* window) ImVec2 tooltip_pos = ref_pos + TOOLTIP_DEFAULT_OFFSET_MOUSE * scale; ImRect r_avoid; - if (g.NavCursorVisible && g.NavDisableMouseHover && !g.IO.ConfigNavMoveSetMousePos) + if (g.NavCursorVisible && g.NavHighlightItemUnderNav && !g.IO.ConfigNavMoveSetMousePos) r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8); else r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * scale, ref_pos.y + 24 * scale); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important. @@ -12270,7 +12270,7 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) window->NavRectRel[nav_layer] = WindowRectAbsToRel(window, g.LastItemData.NavRect); if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad) - g.NavDisableMouseHover = true; + g.NavHighlightItemUnderNav = true; else g.NavCursorVisible = false; @@ -12739,7 +12739,7 @@ void ImGui::NavRestoreHighlightAfterMove() { ImGuiContext& g = *GImGui; g.NavCursorVisible = true; - g.NavDisableMouseHover = g.NavMousePosDirty = true; + g.NavHighlightItemUnderNav = g.NavMousePosDirty = true; } static inline void ImGui::NavUpdateAnyRequestFlag() @@ -12789,7 +12789,7 @@ static ImGuiInputSource ImGui::NavCalcPreferredRefPosSource() const bool activated_shortcut = g.ActiveId != 0 && g.ActiveIdFromShortcut && g.ActiveId == g.LastItemData.ID; // Testing for !activated_shortcut here could in theory be removed if we decided that activating a remote shortcut altered one of the g.NavDisableXXX flag. - if ((!g.NavCursorVisible || !g.NavDisableMouseHover || !window) && !activated_shortcut) + if ((!g.NavCursorVisible || !g.NavHighlightItemUnderNav || !window) && !activated_shortcut) return ImGuiInputSource_Mouse; else return ImGuiInputSource_Keyboard; // or Nav in general @@ -12897,7 +12897,7 @@ static void ImGui::NavUpdate() // Schedule mouse position update (will be done at the bottom of this function, after 1) processing all move requests and 2) updating scrolling) bool set_mouse_pos = false; if (g.NavMousePosDirty && g.NavIdIsAlive) - if (g.NavCursorVisible && g.NavDisableMouseHover && g.NavWindow) + if (g.NavCursorVisible && g.NavHighlightItemUnderNav && g.NavWindow) set_mouse_pos = true; g.NavMousePosDirty = false; IM_ASSERT(g.NavLayer == ImGuiNavLayer_Main || g.NavLayer == ImGuiNavLayer_Menu); @@ -13004,7 +13004,7 @@ static void ImGui::NavUpdate() if (!nav_keyboard_active && !nav_gamepad_active) { g.NavCursorVisible = false; - g.NavDisableMouseHover = set_mouse_pos = false; + g.NavHighlightItemUnderNav = set_mouse_pos = false; } // Update mouse position if requested @@ -13717,7 +13717,7 @@ static void ImGui::NavUpdateWindowing() const float NAV_MOVE_SPEED = 800.0f; const float move_step = NAV_MOVE_SPEED * io.DeltaTime * ImMin(io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y); g.NavWindowingAccumDeltaPos += nav_move_dir * move_step; - g.NavDisableMouseHover = true; + g.NavHighlightItemUnderNav = true; ImVec2 accum_floored = ImTrunc(g.NavWindowingAccumDeltaPos); if (accum_floored.x != 0.0f || accum_floored.y != 0.0f) { @@ -15823,7 +15823,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible); Text("NavActivateId/DownId/PressedId: %08X/%08X/%08X", g.NavActivateId, g.NavActivateDownId, g.NavActivatePressedId); Text("NavActivateFlags: %04X", g.NavActivateFlags); - Text("NavCursorVisible: %d, NavDisableMouseHover: %d", g.NavCursorVisible, g.NavDisableMouseHover); + Text("NavCursorVisible: %d, NavHighlightItemUnderNav: %d", g.NavCursorVisible, g.NavHighlightItemUnderNav); Text("NavFocusScopeId = 0x%08X", g.NavFocusScopeId); Text("NavFocusRoute[] = "); for (int path_n = g.NavFocusRoute.Size - 1; path_n >= 0; path_n--) diff --git a/imgui_internal.h b/imgui_internal.h index 94e0cb0e0..85ca13910 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -833,7 +833,7 @@ enum ImGuiItemFlagsPrivate_ ImGuiItemFlags_MixedValue = 1 << 12, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets) ImGuiItemFlags_NoWindowHoverableCheck = 1 << 13, // false // Disable hoverable check in ItemHoverable() ImGuiItemFlags_AllowOverlap = 1 << 14, // false // Allow being overlapped by another widget. Not-hovered to Hovered transition deferred by a frame. - ImGuiItemFlags_NoNavDisableMouseHover = 1 << 15, // false // Nav keyboard/gamepad mode doesn't disable hover. + ImGuiItemFlags_NoNavDisableMouseHover = 1 << 15, // false // Nav keyboard/gamepad mode doesn't disable hover highlight (behave as if NavHighlightItemUnderNav==false). ImGuiItemFlags_NoMarkEdited = 1 << 16, // false // Skip calling MarkItemEdited() // Controlled by widget code @@ -2133,6 +2133,10 @@ struct ImGuiContext ImVector Viewports; // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData. // Gamepad/keyboard Navigation + bool NavCursorVisible; // Nav focus cursor/rectangle is visible? We hide it after a mouse click. We show it after a nav move. + bool NavHighlightItemUnderNav; // Disable mouse hovering highlight. Highlight navigation focused item instead of mouse hovered item. + //bool NavDisableHighlight; // Old name for !g.NavCursorVisible before 1.91.4 (2024/10/18). OPPOSITE VALUE (g.NavDisableHighlight == !g.NavCursorVisible) + //bool NavDisableMouseHover; // Old name for g.NavHighlightItemUnderNav before 1.91.1 (2024/10/18) this was called When user starts using keyboard/gamepad, we hide mouse hovering highlight until mouse is touched again. ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow' ImGuiID NavId; // Focused item for navigation ImGuiID NavFocusScopeId; // Focused focus scope (e.g. selection code often wants to "clear other items" when landing on an item of the same scope) @@ -2150,9 +2154,6 @@ struct ImGuiContext ImGuiSelectionUserData NavLastValidSelectionUserData; // Last valid data passed to SetNextItemSelectionUser(), or -1. For current window. Not reset when focusing an item that doesn't have selection data. bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRectRel is valid bool NavMousePosDirty; // When set we will update mouse position if io.ConfigNavMoveSetMousePos is set (not enabled by default) - bool NavCursorVisible; // Nav focus rectangle is visible? We hide it after a mouse click. We show it after a nav move. - //bool NavDisableHighlight; // Before 1.91.4 (2024/10/18) we used g.NavDisableHighlight. g.NavCursorVisible is the new variable name, with opposite value (g.NavDisableHighlight = !g.NavCursorVisible) - bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again. // Navigation: Init & Move Requests bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest this is to perform early out in ItemAdd() diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index e5f2acc8d..3b28daa4d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -625,7 +625,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool // Gamepad/Keyboard handling // We report navigated and navigation-activated items as hovered but we don't set g.HoveredId to not interfere with mouse. - if (g.NavId == id && g.NavCursorVisible && g.NavDisableMouseHover) + if (g.NavId == id && g.NavCursorVisible && g.NavHighlightItemUnderNav) if (!(flags & ImGuiButtonFlags_NoHoveredOnFocus)) hovered = true; if (g.NavActivateDownId == id) @@ -4476,7 +4476,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.ItemFlags | ImGuiItemFlags_NoNavDisableMouseHover); if (hovered) SetMouseCursor(ImGuiMouseCursor_TextInput); - if (hovered && g.NavDisableMouseHover) + if (hovered && g.NavHighlightItemUnderNav) hovered = false; // We are only allowed to access the state if we are already the active widget. @@ -6628,7 +6628,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l if ((flags & ImGuiTreeNodeFlags_OpenOnMask_) == 0 || (g.NavActivateId == id && !is_multi_select)) toggled = true; // Single click if (flags & ImGuiTreeNodeFlags_OpenOnArrow) - toggled |= is_mouse_x_over_arrow && !g.NavDisableMouseHover; // Lightweight equivalent of IsMouseHoveringRect() since ButtonBehavior() already did the job + toggled |= is_mouse_x_over_arrow && !g.NavHighlightItemUnderNav; // Lightweight equivalent of IsMouseHoveringRect() since ButtonBehavior() already did the job if ((flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) && g.IO.MouseClickedCount[0] == 2) toggled = true; // Double click } @@ -6998,7 +6998,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl // Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover))) { - if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent) + if (!g.NavHighlightItemUnderNav && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent) { SetNavID(id, window->DC.NavLayerCurrent, g.CurrentFocusScopeId, WindowRectAbsToRel(window, bb)); // (bb == NavRect) g.NavCursorVisible = false; @@ -8625,7 +8625,7 @@ void ImGui::EndMenuBar() FocusWindow(window); SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]); g.NavCursorVisible = false; // Hide nav cursor for the current frame so we don't see the intermediary selection. - g.NavDisableMouseHover = g.NavMousePosDirty = true; + g.NavHighlightItemUnderNav = g.NavMousePosDirty = true; NavMoveRequestForward(g.NavMoveDir, g.NavMoveClipDir, g.NavMoveFlags, g.NavMoveScrollFlags); // Repeat } } @@ -8833,7 +8833,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) if (!enabled) EndDisabled(); - const bool hovered = (g.HoveredId == id) && enabled && !g.NavDisableMouseHover; + const bool hovered = (g.HoveredId == id) && enabled && !g.NavHighlightItemUnderNav; if (menuset_is_open) PopItemFlag(); @@ -8868,7 +8868,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) // The 'HovereWindow == window' check creates an inconsistency (e.g. moving away from menu slowly tends to hit same window, whereas moving away fast does not) // But we also need to not close the top-menu menu when moving over void. Perhaps we should extend the triangle check to a larger polygon. // (Remember to test this on BeginPopup("A")->BeginMenu("B") sequence which behaves slightly differently as B isn't a Child of A and hovering isn't shared.) - if (menu_is_open && !hovered && g.HoveredWindow == window && !moving_toward_child_menu && !g.NavDisableMouseHover && g.ActiveId == 0) + if (menu_is_open && !hovered && g.HoveredWindow == window && !moving_toward_child_menu && !g.NavHighlightItemUnderNav && g.ActiveId == 0) want_close = true; // Open