From de50c276ec960b0e7b9f0d700157f76110d60b75 Mon Sep 17 00:00:00 2001
From: ed <eddavies95@gmail.com>
Date: Thu, 18 Nov 2021 15:43:22 +0000
Subject: [PATCH] Tooltip:  Show manually shown tips until a dismissal mouse
 event occurs

---
 .../windows/juce_TooltipWindow.cpp            | 52 +++++++------------
 .../windows/juce_TooltipWindow.h              |  8 ++-
 2 files changed, 26 insertions(+), 34 deletions(-)

diff --git a/modules/juce_gui_basics/windows/juce_TooltipWindow.cpp b/modules/juce_gui_basics/windows/juce_TooltipWindow.cpp
index 594967240..513638f81 100644
--- a/modules/juce_gui_basics/windows/juce_TooltipWindow.cpp
+++ b/modules/juce_gui_basics/windows/juce_TooltipWindow.cpp
@@ -164,7 +164,7 @@ String TooltipWindow::getTipFor (Component& c)
 
 void TooltipWindow::hideTip()
 {
-    if (! reentrant)
+    if (isVisible() && ! reentrant)
     {
         tipShowing = {};
         manuallyShownTip = {};
@@ -173,6 +173,8 @@ void TooltipWindow::hideTip()
         removeFromDesktop();
         setVisible (false);
 
+        lastHideTime = Time::getApproximateMillisecondCounter();
+
        #if JUCE_DEBUG
         activeTooltipWindows.removeAllInstancesOf (this);
        #endif
@@ -194,25 +196,20 @@ std::unique_ptr<AccessibilityHandler> TooltipWindow::createAccessibilityHandler(
 
 void TooltipWindow::timerCallback()
 {
-    auto& desktop = Desktop::getInstance();
-    auto mouseSource = desktop.getMainMouseSource();
-    auto now = Time::getApproximateMillisecondCounter();
-
+    const auto mouseSource = Desktop::getInstance().getMainMouseSource();
     auto* newComp = mouseSource.isTouch() ? nullptr : mouseSource.getComponentUnderMouse();
 
-    if (newComp == nullptr || getParentComponent() == nullptr || newComp->getPeer() == getPeer())
+    if (manuallyShownTip.isNotEmpty())
     {
-        const auto componentChanged = (newComp != lastComponentUnderMouse);
+        if (dismissalMouseEventOccured || newComp == nullptr)
+            hideTip();
 
-        const auto newTip = [this, &newComp, componentChanged]
-        {
-            if (dynamic_cast<TooltipClient*> (newComp) != nullptr)
-                return getTipFor (*newComp);
-
-            return componentChanged ? String() : manuallyShownTip;
-        }();
+        return;
+    }
 
-        const auto tipChanged = (newTip != lastTipUnderMouse || componentChanged);
+    if (newComp == nullptr || getParentComponent() == nullptr || newComp->getPeer() == getPeer())
+    {
+        const auto newTip = newComp != nullptr ? getTipFor (*newComp) : String();
 
         lastComponentUnderMouse = newComp;
         lastTipUnderMouse = newTip;
@@ -221,19 +218,16 @@ void TooltipWindow::timerCallback()
         const auto mouseMovedQuickly = (mousePos.getDistanceFrom (lastMousePos) > 12);
         lastMousePos = mousePos;
 
+        const auto tipChanged = (newTip != lastTipUnderMouse || newComp != lastComponentUnderMouse);
+        const auto now = Time::getApproximateMillisecondCounter();
+
         if (tipChanged || dismissalMouseEventOccured || mouseMovedQuickly)
             lastCompChangeTime = now;
 
-        auto showTip = [this, &mouseSource, &mousePos, &newTip]
+        const auto showTip = [this, &mouseSource, &mousePos, &newTip]
         {
-            if (mouseSource.getLastMouseDownPosition() == lastMousePos)
-                return;
-
-            const auto isShowingManualTip = (manuallyShownTip.isNotEmpty() && manuallyShownTip == newTip);
-
-            displayTipInternal (mousePos.roundToInt(),
-                                newTip,
-                                isShowingManualTip ? ShownManually::yes : ShownManually::no);
+            if (mouseSource.getLastMouseDownPosition() != lastMousePos)
+                displayTipInternal (mousePos.roundToInt(), newTip, ShownManually::no);
         };
 
         if (isVisible() || now < lastHideTime + 500)
@@ -241,17 +235,9 @@ void TooltipWindow::timerCallback()
             // if a tip is currently visible (or has just disappeared), update to a new one
             // immediately if needed..
             if (newComp == nullptr || dismissalMouseEventOccured || newTip.isEmpty())
-            {
-                if (isVisible())
-                {
-                    lastHideTime = now;
-                    hideTip();
-                }
-            }
+                hideTip();
             else if (tipChanged)
-            {
                 showTip();
-            }
         }
         else
         {
diff --git a/modules/juce_gui_basics/windows/juce_TooltipWindow.h b/modules/juce_gui_basics/windows/juce_TooltipWindow.h
index fe430cc5e..158f0df15 100644
--- a/modules/juce_gui_basics/windows/juce_TooltipWindow.h
+++ b/modules/juce_gui_basics/windows/juce_TooltipWindow.h
@@ -84,7 +84,13 @@ public:
     */
     void setMillisecondsBeforeTipAppears (int newTimeMs = 700) noexcept;
 
-    /** Can be called to manually force a tip to be shown at a particular location. */
+    /** Can be called to manually force a tip to be shown at a particular location.
+
+        The tip will be shown until hideTip() is called, or a dismissal mouse event
+        occurs.
+
+        @see hideTip
+    */
     void displayTip (Point<int> screenPosition, const String& text);
 
     /** Can be called to manually hide the tip if it's showing. */
-- 
2.30.1 (Apple Git-130)

