diff --git a/modules/juce_gui_basics/native/juce_mac_Windowing.mm b/modules/juce_gui_basics/native/juce_mac_Windowing.mm index 94daf3fbce..d071dc6895 100644 --- a/modules/juce_gui_basics/native/juce_mac_Windowing.mm +++ b/modules/juce_gui_basics/native/juce_mac_Windowing.mm @@ -446,13 +446,43 @@ Point MouseInputSource::getCurrentRawMousePosition() } } +static ComponentPeer* findPeerContainingPoint (Point globalPos) +{ + for (int i = 0; i < juce::ComponentPeer::getNumPeers(); ++i) + { + auto* peer = juce::ComponentPeer::getPeer (i); + + if (peer->contains (peer->globalToLocal (globalPos).toInt(), false)) + return peer; + } + + return nullptr; +} + void MouseInputSource::setRawMousePosition (Point newPosition) { + const auto oldPosition = Desktop::getInstance().getMainMouseSource().getRawScreenPosition(); + // this rubbish needs to be done around the warp call, to avoid causing a // bizarre glitch.. CGAssociateMouseAndMouseCursorPosition (false); CGWarpMouseCursorPosition (convertToCGPoint (newPosition)); CGAssociateMouseAndMouseCursorPosition (true); + + // Mouse enter and exit events seem to be always generated as a consequence of programmatically + // moving the mouse. However, when the mouse stays within the same peer no mouse move event is + // generated, and we lose track of the correct Component under the mouse. Hence, we need to + // generate this missing event here. + if (auto* peer = findPeerContainingPoint (newPosition); peer != nullptr + && peer == findPeerContainingPoint (oldPosition)) + { + peer->handleMouseEvent (MouseInputSource::InputSourceType::mouse, + peer->globalToLocal (newPosition), + ModifierKeys::currentModifiers, + 0.0f, + 0.0f, + Time::currentTimeMillis()); + } } double Desktop::getDefaultMasterScale()