From ac2c863ffa6850e7939df652bdc5f7e6f962636b Mon Sep 17 00:00:00 2001 From: reuk Date: Tue, 1 Jul 2025 18:48:56 +0100 Subject: [PATCH] PopupMenu: Add mouse movement timeout back in This reimplements similar functionality to that removed in d39789b021178e951b84abc5a08eac63f2d4aa10. Unlike the previous implementation, this version will still wait for the mouse to move over the menu before the countdown timer is allowed to start. This should avoid the situation where menu items are accidentally triggered on mouse-up, after a menu opens under the pointer in response to a mouse-down. --- .../juce_gui_basics/menus/juce_PopupMenu.cpp | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/modules/juce_gui_basics/menus/juce_PopupMenu.cpp b/modules/juce_gui_basics/menus/juce_PopupMenu.cpp index ccddbe0f0d..18ea5eb37f 100644 --- a/modules/juce_gui_basics/menus/juce_PopupMenu.cpp +++ b/modules/juce_gui_basics/menus/juce_PopupMenu.cpp @@ -1423,7 +1423,7 @@ public: private: Point lastMousePos; double scrollAcceleration = 0; - uint32 lastScrollTime; + uint32 lastScrollTime = 0, lastMoveTime = 0; bool isDown = false; // Although most mouse movements can be handled inside mouse event callbacks, scrolling of menus @@ -1454,7 +1454,7 @@ private: window.showSubMenuFor (window.currentChild); } - highlightItemUnderMouse (globalMousePos, localMousePos); + highlightItemUnderMouse (globalMousePos, localMousePos, timeNow); const bool overScrollArea = scrollIfNecessary (localMousePos, timeNow); const bool isOverAny = window.isOverAnyMenu(); @@ -1498,19 +1498,25 @@ private: } } - void highlightItemUnderMouse (Point globalMousePos, Point localMousePos) + void highlightItemUnderMouse (Point globalMousePos, Point localMousePos, uint32 timeNow) { + const auto mouseTimedOut = lastMoveTime != 0 && 350 < (timeNow - lastMoveTime); const auto mouseHasMoved = 2 < lastMousePos.getDistanceFrom (globalMousePos); - - if (! mouseHasMoved) - return; - const auto isMouseOver = window.reallyContains (localMousePos, true); - if (isMouseOver) + if (mouseHasMoved && isMouseOver) + { window.disableMouseMoves = false; + lastMoveTime = timeNow; + } - if (window.disableMouseMoves || (window.activeSubMenu != nullptr && window.activeSubMenu->isOverChildren())) + if (! mouseHasMoved && ! mouseTimedOut) + return; + + if (window.disableMouseMoves) + return; + + if (window.activeSubMenu != nullptr && window.activeSubMenu->isOverChildren()) return; const auto isMovingTowardsMenu = isMouseOver