From 7bcb1d3816cf0eea13a0f716a9779151ef203f76 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 27 Sep 2017 22:59:40 +0200 Subject: [PATCH 1/6] Internals: ButtonBehavior(), IsHovered() moved the responsability of flatten_child higher level to ButtonBehavior() - not super sure about the elegance of this --- imgui.cpp | 16 ++++++++++++---- imgui_internal.h | 2 +- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c9b7031f..747fcba5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1951,7 +1951,6 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) // This is roughly matching the behavior of internal-facing IsHovered() // - 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()) -// - we don't expose the flatten_child feature that IsHovered() has, which is only used by the window resizing widget (may rework this) bool ImGui::IsItemHovered() { ImGuiContext& g = *GImGui; @@ -1972,13 +1971,13 @@ bool ImGui::IsItemRectHovered() } // Internal facing IsHovered() differs slightly from IsItemHovered(). -bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs) +bool ImGui::IsHovered(const ImRect& bb, ImGuiID id) { ImGuiContext& g = *GImGui; if (g.HoveredId == 0 || g.HoveredId == id || g.HoveredIdAllowOverlap) { ImGuiWindow* window = g.CurrentWindow; - if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow)) + if (g.HoveredWindow == window) if (g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowOverlap) if (IsMouseHoveringRect(bb.Min, bb.Max)) if (IsWindowContentHoverable(g.HoveredRootWindow)) @@ -4274,6 +4273,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && !(flags & ImGuiWindowFlags_NoResize)) { // Manual resize + // Using the FlattenChilds button flag, we make the resize button accessible even if we are hovering over a child window const ImVec2 br = window->Rect().GetBR(); const ImRect resize_rect(br - ImVec2(resize_corner_size * 0.75f, resize_corner_size * 0.75f), br); const ImGuiID resize_id = window->GetID("#RESIZE"); @@ -5673,8 +5673,16 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool if ((flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick)) == 0) flags |= ImGuiButtonFlags_PressedOnClickRelease; + ImGuiWindow* backup_hovered_window = g.HoveredWindow; + if ((flags & ImGuiButtonFlags_FlattenChilds) && g.HoveredRootWindow == window) + g.HoveredWindow = window; + bool pressed = false; - bool hovered = IsHovered(bb, id, (flags & ImGuiButtonFlags_FlattenChilds) != 0); + bool hovered = IsHovered(bb, id); + + if ((flags & ImGuiButtonFlags_FlattenChilds) && g.HoveredRootWindow == window) + g.HoveredWindow = backup_hovered_window; + if (hovered) { SetHoveredID(id); diff --git a/imgui_internal.h b/imgui_internal.h index a1192be9..9329e461 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -771,7 +771,7 @@ namespace ImGui IMGUI_API void ItemSize(const ImRect& bb, float text_offset_y = 0.0f); IMGUI_API bool ItemAdd(const ImRect& bb, const ImGuiID* id); IMGUI_API bool IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged); - IMGUI_API bool IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs = false); + IMGUI_API bool IsHovered(const ImRect& bb, ImGuiID id); IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop = true); // Return true if focus is requested IMGUI_API void FocusableItemUnregister(ImGuiWindow* window); IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y); From c5a79deb38774c76ff416e8f673bf080650f1b52 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 27 Sep 2017 23:10:46 +0200 Subject: [PATCH 2/6] IsItemHovered(), IsHovered(): Shallow tweaks to make them more symetrical. Removed one set of braces. --- imgui.cpp | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 747fcba5..1f1c4f64 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1954,12 +1954,14 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) bool ImGui::IsItemHovered() { ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; - if (g.HoveredWindow == window) - if (g.ActiveId == 0 || g.ActiveId == window->DC.LastItemId || g.ActiveIdAllowOverlap || g.ActiveId == window->MoveId) - if (IsMouseHoveringRect(window->DC.LastItemRect.Min, window->DC.LastItemRect.Max)) - if (IsWindowContentHoverable(window)) - return true; + if (g.HoveredWindow != window) + return false; + if (g.ActiveId == 0 || g.ActiveId == window->DC.LastItemId || g.ActiveIdAllowOverlap || g.ActiveId == window->MoveId) + if (IsMouseHoveringRect(window->DC.LastItemRect.Min, window->DC.LastItemRect.Max)) + if (IsWindowContentHoverable(window)) + return true; return false; } @@ -1974,15 +1976,17 @@ bool ImGui::IsItemRectHovered() bool ImGui::IsHovered(const ImRect& bb, ImGuiID id) { ImGuiContext& g = *GImGui; - if (g.HoveredId == 0 || g.HoveredId == id || g.HoveredIdAllowOverlap) - { - ImGuiWindow* window = g.CurrentWindow; - if (g.HoveredWindow == window) - if (g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowOverlap) - if (IsMouseHoveringRect(bb.Min, bb.Max)) - if (IsWindowContentHoverable(g.HoveredRootWindow)) - return true; - } + if (g.HoveredId != 0 && g.HoveredId != id && !g.HoveredIdAllowOverlap) + return false; + + ImGuiWindow* window = g.CurrentWindow; + if (g.HoveredWindow != window) + return false; + if (g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowOverlap) + if (IsMouseHoveringRect(bb.Min, bb.Max)) + if (IsWindowContentHoverable(g.HoveredRootWindow)) + return true; + return false; } From 2b7d4c713e9982ea7b668b38cbdeba344c0ca5d1 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 27 Sep 2017 23:31:03 +0200 Subject: [PATCH 3/6] Internals: Moved IsWindowContentHoverable() in the file --- imgui.cpp | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1f1c4f64..4d53b8b3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -605,7 +605,6 @@ static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, I static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond); static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs); static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags); -static inline bool IsWindowContentHoverable(ImGuiWindow* window); static void ClearSetNextWindowData(); static void CheckStacksSize(ImGuiWindow* window, bool write); static void Scrollbar(ImGuiWindow* window, bool horizontal); @@ -1901,6 +1900,19 @@ void ImGui::KeepAliveID(ImGuiID id) g.ActiveIdIsAlive = true; } +static inline bool IsWindowContentHoverable(ImGuiWindow* window) +{ + // 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; + + return true; +} + // Advance cursor given item size for layout. void ImGui::ItemSize(const ImVec2& size, float text_offset_y) { @@ -5647,19 +5659,6 @@ void ImGui::LabelText(const char* label, const char* fmt, ...) va_end(args); } -static inline bool IsWindowContentHoverable(ImGuiWindow* window) -{ - // 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; - - return true; -} - bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags) { ImGuiContext& g = *GImGui; From eca74d55c729ca3007e47ddebec83697a9434911 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Sep 2017 00:05:18 +0200 Subject: [PATCH 4/6] IsItemHovered(), IsHovered(): Shallow tweaks, eventually removed all the braces. --- imgui.cpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4d53b8b3..fcf947b3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1970,12 +1970,13 @@ bool ImGui::IsItemHovered() ImGuiWindow* window = g.CurrentWindow; if (g.HoveredWindow != window) return false; - if (g.ActiveId == 0 || g.ActiveId == window->DC.LastItemId || g.ActiveIdAllowOverlap || g.ActiveId == window->MoveId) - if (IsMouseHoveringRect(window->DC.LastItemRect.Min, window->DC.LastItemRect.Max)) - if (IsWindowContentHoverable(window)) - return true; - - return false; + if (g.ActiveId != 0 && g.ActiveId != window->DC.LastItemId && !g.ActiveIdAllowOverlap && g.ActiveId != window->MoveId) + return false; + if (!IsMouseHoveringRect(window->DC.LastItemRect.Min, window->DC.LastItemRect.Max)) + return false; + if (!IsWindowContentHoverable(window)) + return false; + return true; } bool ImGui::IsItemRectHovered() @@ -1994,12 +1995,13 @@ bool ImGui::IsHovered(const ImRect& bb, ImGuiID id) ImGuiWindow* window = g.CurrentWindow; if (g.HoveredWindow != window) return false; - if (g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowOverlap) - if (IsMouseHoveringRect(bb.Min, bb.Max)) - if (IsWindowContentHoverable(g.HoveredRootWindow)) - return true; - - return false; + if (g.ActiveId != 0 && g.ActiveId != id && !g.ActiveIdAllowOverlap) + return false; + if (!IsMouseHoveringRect(bb.Min, bb.Max)) + return false; + if (!IsWindowContentHoverable(g.HoveredRootWindow)) + return false; + return true; } bool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged) From 2159629e9ee20cfbf2d814761edb95ef76bd333b Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Sep 2017 00:05:35 +0200 Subject: [PATCH 5/6] Removed another msileading difference between the hovered functions (IsWindowContentHoverable() uses the root window already). Sorry for the commit spam! (making small commit to easily be able to Bisect those in case I make a mistake) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index fcf947b3..150ebf62 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1999,7 +1999,7 @@ bool ImGui::IsHovered(const ImRect& bb, ImGuiID id) return false; if (!IsMouseHoveringRect(bb.Min, bb.Max)) return false; - if (!IsWindowContentHoverable(g.HoveredRootWindow)) + if (!IsWindowContentHoverable(window)) return false; return true; } From fafe65a8fcb003bb9140bd9624ef5f218f631f93 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Sep 2017 00:21:47 +0200 Subject: [PATCH 6/6] Refactor to move the responsability of SetHovered() to ItemHoverable() - previously IsHovered(). Simpler and the parallel to ItemAdd is clearer with the new name. --- imgui.cpp | 41 +++++++++++++++-------------------------- imgui_internal.h | 2 +- 2 files changed, 16 insertions(+), 27 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 150ebf62..59b4c275 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1961,7 +1961,7 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) return true; } -// This is roughly matching the behavior of internal-facing IsHovered() +// This is roughly matching the behavior of internal-facing ItemHoverable() which is // - 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()) bool ImGui::IsItemHovered() { @@ -1985,8 +1985,8 @@ bool ImGui::IsItemRectHovered() return IsMouseHoveringRect(window->DC.LastItemRect.Min, window->DC.LastItemRect.Max); } -// Internal facing IsHovered() differs slightly from IsItemHovered(). -bool ImGui::IsHovered(const ImRect& bb, ImGuiID id) +// Internal facing ItemHoverable() used when submitting widgets. Differs slightly from IsItemHovered(). +bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id) { ImGuiContext& g = *GImGui; if (g.HoveredId != 0 && g.HoveredId != id && !g.HoveredIdAllowOverlap) @@ -2001,6 +2001,8 @@ bool ImGui::IsHovered(const ImRect& bb, ImGuiID id) return false; if (!IsWindowContentHoverable(window)) return false; + + SetHoveredID(id); return true; } @@ -5683,14 +5685,13 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool g.HoveredWindow = window; bool pressed = false; - bool hovered = IsHovered(bb, id); + bool hovered = ItemHoverable(bb, id); if ((flags & ImGuiButtonFlags_FlattenChilds) && g.HoveredRootWindow == window) g.HoveredWindow = backup_hovered_window; if (hovered) { - SetHoveredID(id); if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt)) { // | CLICKING | HOLDING with ImGuiButtonFlags_Repeat @@ -6757,10 +6758,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c ItemSize(total_bb, style.FramePadding.y); return false; } - - const bool hovered = IsHovered(frame_bb, id); - if (hovered) - SetHoveredID(id); + const bool hovered = ItemHoverable(frame_bb, id); if (!display_format) display_format = "%.3f"; @@ -6814,10 +6812,7 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float ItemSize(bb, style.FramePadding.y); if (!ItemAdd(frame_bb, &id)) return false; - - const bool hovered = IsHovered(frame_bb, id); - if (hovered) - SetHoveredID(id); + const bool hovered = ItemHoverable(frame_bb, id); if (!display_format) display_format = "%.3f"; @@ -7057,10 +7052,7 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f ItemSize(total_bb, style.FramePadding.y); return false; } - - const bool hovered = IsHovered(frame_bb, id); - if (hovered) - SetHoveredID(id); + const bool hovered = ItemHoverable(frame_bb, id); if (!display_format) display_format = "%.3f"; @@ -7263,6 +7255,7 @@ void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_ge ItemSize(total_bb, style.FramePadding.y); if (!ItemAdd(total_bb, NULL)) return; + const bool hovered = ItemHoverable(inner_bb, 0); // Determine scale from values if not specified if (scale_min == FLT_MAX || scale_max == FLT_MAX) @@ -7290,7 +7283,7 @@ void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_ge // Tooltip on hover int v_hovered = -1; - if (IsHovered(inner_bb, 0)) + if (hovered) { const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f); const int v_idx = (int)(t * item_count); @@ -7851,6 +7844,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 if (!ItemAdd(total_bb, &id)) return false; } + const bool hovered = ItemHoverable(frame_bb, id); + if (hovered) + g.MouseCursor = ImGuiMouseCursor_TextInput; // Password pushes a temporary font with only a fallback glyph if (is_password) @@ -7876,12 +7872,6 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 const bool focus_requested_by_code = focus_requested && (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent); const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code; - const bool hovered = IsHovered(frame_bb, id); - if (hovered) - { - SetHoveredID(id); - g.MouseCursor = ImGuiMouseCursor_TextInput; - } const bool user_clicked = hovered && io.MouseClicked[0]; const bool user_scrolled = is_multiline && g.ActiveId == 0 && edit_state.Id == id && g.ActiveIdPreviousFrame == draw_window->GetIDNoKeepAlive("#SCROLLY"); @@ -9073,8 +9063,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) if (!enabled) PopStyleColor(); } - bool hovered = enabled && IsHovered(window->DC.LastItemRect, id); - + const bool hovered = enabled && ItemHoverable(window->DC.LastItemRect, id); if (menuset_is_open) g.NavWindow = backed_nav_window; diff --git a/imgui_internal.h b/imgui_internal.h index 9329e461..67ccf4eb 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -771,7 +771,7 @@ namespace ImGui IMGUI_API void ItemSize(const ImRect& bb, float text_offset_y = 0.0f); IMGUI_API bool ItemAdd(const ImRect& bb, const ImGuiID* id); IMGUI_API bool IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged); - IMGUI_API bool IsHovered(const ImRect& bb, ImGuiID id); + IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id); IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop = true); // Return true if focus is requested IMGUI_API void FocusableItemUnregister(ImGuiWindow* window); IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y);