Hi all,
I think I’ve found a mouse bug on Mac (Monterey 12.3.1, JUCE 6.1.6). It’s based on the following assumption:
Under normal circumstances, the MouseEvent
parameter passed into mouseEnter()
, mouseMove()
, mouseDown()
, mouseUp()
and mouseDrag()
should always contain mouse coordinates that fall inside the target components bounds.
I realize there will be exceptions (eg. it might not apply to mouseExit()
, and unexpected things can happen if you misuse mouse listeners), but as a general rule, you wouldn’t expect your components mouseMove()
handler to fire unless the mouse was actually inside it!
Well, assuming that’s correct, I’m seeing mouse methods getting called with MouseEvent
coordinates that fall 1 pixel outside of the component bounds.
It happens reliably for me, but only on Mac. FWIW, I’m using the same Logitech mouse to test on Mac and Windows.
If I understand correctly, it boils down to the fact that JUCE uses float
mouse coordinates internally. On Windows, the x/y values are always whole numbers but on Mac they’re always decimals. So, while you might see x coordinates of 123.456 and 654.321 on Mac, they’d just be 123.000 and 654.000 on Windows.
That’s probably expected due to OS differences, but it leads to a rounding error in the MouseInputSourceInternal::sendMouse___()
methods which can result in ‘off-by-one’ MouseEvent
coordinates. Subtle, but potentially nasty.
For us, it manifests as unexpected behavior and asserts in our UI code, and it happens surprisingly often.
You can test it in DemoRunner. Add the following assert in juce_Component.cpp line 2642 (JUCE 6.1.6), just before the call to mouseMove()
in Component::internalMouseMove()
:
jassert (getLocalBounds().contains (me.x, me.y));
Obviously, the assert simply checks that the MouseEvent
x/y coordinates are inside the component. Build it, fire it up, then move the mouse around the UI and wait for it to fire. It happens quite a lot.
A prompt investigation and fix would be very much appreciated
Many thanks,
Ben