diff --git a/docs/HLSD/tooltip-illustrations.md b/docs/HLSD/tooltip-illustrations.md index 1189c89c3f..dc52e9ac93 100644 --- a/docs/HLSD/tooltip-illustrations.md +++ b/docs/HLSD/tooltip-illustrations.md @@ -57,7 +57,10 @@ afterwards rather than the short one: having just let go of a slider is not a re picture of it. A pointer resting on a control produces no events, and the canvas only renders when something asks it -to, so the wait has to ask for its own frames, and so does an animation once one is on screen. Both use +to, so the wait has to ask for its own frames, and so does an animation once one is on screen. So does +a tooltip that has just appeared, animated or not: ImGui hides a window on the first frame it is +submitted while it measures it, and does so every time a tooltip reappears because those windows are +recycled, so the frame a tooltip is decided on is never the frame it is seen on. Both use `GLCanvas3D::request_extra_frame()`, which ends `on_idle()` with `evt.RequestMore()` and so obliges wx to deliver the next idle. `schedule_extra_frame()` is not enough on its own: it only arranges a timer whose event an idle event is assumed to follow, and on_idle renders nothing unless the canvas was diff --git a/src/slic3r/GUI/Gizmos/GLGizmoTextureDisplacement.cpp b/src/slic3r/GUI/Gizmos/GLGizmoTextureDisplacement.cpp index 2b04e0eef7..c513077ebd 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoTextureDisplacement.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoTextureDisplacement.cpp @@ -3764,6 +3764,17 @@ void GLGizmoTextureDisplacement::panel_tooltip(const std::string &text, const st } m_tip_last_shown = now; + // ImGui hides a window on the first frame it is submitted, to measure it before showing it - and + // for a tooltip it does so every time one reappears, because the windows are recycled (see the + // Popup|Tooltip branch of Begin()). So the frame on which a tooltip is decided is never the frame + // on which it is seen, and one that then asks for nothing more stays invisible until the next pixel + // of mouse movement happens to produce another frame. Keep frames coming until it has settled. + const int shown_frame = ImGui::GetFrameCount(); + m_tip_settled = (shown_frame == m_tip_shown_frame + 1) ? m_tip_settled + 1 : 0; + m_tip_shown_frame = shown_frame; + if (m_tip_settled < 2) + m_parent.request_extra_frame(); + const ImGuiStyle &style = ImGui::GetStyle(); const float gap = m_imgui->scaled(0.5f); const float wrap = m_imgui->scaled(20.f); diff --git a/src/slic3r/GUI/Gizmos/GLGizmoTextureDisplacement.hpp b/src/slic3r/GUI/Gizmos/GLGizmoTextureDisplacement.hpp index 7762b95e3e..c99d7dcee4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoTextureDisplacement.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoTextureDisplacement.hpp @@ -1066,6 +1066,10 @@ private: ImVec2 m_tip_item{-1.f, -1.f}; double m_tip_hover_since = 0.; double m_tip_last_shown = -1e9; + // The frame a tooltip was last drawn on, and how many it has been drawn on in a row: ImGui hides + // one on its first frame while it measures it, so it has to be kept on screen to be seen at all. + int m_tip_shown_frame = -2; + int m_tip_settled = 0; }; } // namespace Slic3r::GUI