You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This sample code reproduces the problem. On MacOS, create a button as a child NSView of the current component's window, make sure it's visible etc, and then mouse over it. What you'll see is that it may temporarily flash to the highlighted isOver state, it will immediately revert to not being highlighted, as if the mouse exited it (even though it didn't).
I have debugged this fairly extensively, and I can explain the problem, and I have a possible solution but it needs to be vetted by someone who understands this stuff more than I do.
What's happening is that both the parent and the child NSView that JUCE creates have NSTrackingAreas installed. These areas are firing mouse events for both the parent and child windows when the mouse is over the child window (despite the NSTrackingInVisibleRect option being set -- it does not prevent this).
Now for methods like redirectMouseEnter() and redirectMouseExit(), this is handled properly by checking that the NSEvent's tracking area is actually the one installed for the current component's NSView.
But for the redirectMouseMove() method, that's not possible as [ev trackingArea] is not defined for this type of event. So what happens is the isWindowAtPoint() method returns true for both the parent and child windows, and they BOTH call sendMouseEvent(), leading to the current component changing repeatedly as the mouse moves. When the current component changes, JUCE calls mouseExit() for the previous component. It so happens that redirectMouseMove() is called in the order of child, then parent, so the button gets exited over and over as JUCE sees the mouseMove in the parent.
My proposed solution is to check if the top-level view at the mouse coordinates is, in fact, the view associated with the NSViewComponentPeer object on which redirectMouseMove() is called. So instead of:
if (isWindowAtPoint ([ev window], screenPos)) {
sendMouseEvent (ev);
} else
// moved into another window which overlaps this one, so trigger an exit
handleMouseEvent (...)
It would be:
if (isWindowAtPoint ([ev window], screenPos)) {
if ([[[ev window] contentView] hitTest: windowPos] == view) {
sendMouseEvent (ev);
}
} else
// moved into another window which overlaps this one, so trigger an exit
handleMouseEvent (...)
This solution does indeed fix things for my test case. But perhaps it causes issues I'm not aware of, or is not general enough, I'm not sure (which is why I didn't submit a pull request).
What is the expected behaviour?
Mousing over the TextButton in the example above should cause it to be highlighted in the isOver state until the mouse is moved out of the bounds of the button.
Operating systems
macOS
What versions of the operating systems?
Sonoma
Architectures
ARM, 64-bit
Stacktrace
No response
Plug-in formats (if applicable)
No response
Plug-in host applications (DAWs) (if applicable)
No response
Testing on the develop branch
The bug is present on the develop branch
Code of Conduct
I agree to follow the Code of Conduct
The text was updated successfully, but these errors were encountered:
Actually it seems so far like my proposed fix works. I can't find anything that it breaks, although it's possible that I'm not being creative enough... ? I'm going to submit a pull request.
Thanks for your patience. We've now added a fix for this issue on the develop branch.
The fix we merged is fairly similar to the one you suggested, but we call the NSViewComponentPeer::contains function rather than calling hitTest directly:
This also unearthed an issue where the argument to hitTest inside NSViewComponentPeer::contains was not correctly using the superview's coordinate space. That issue is addressed here:
Detailed steps on how to reproduce the bug
This sample code reproduces the problem. On MacOS, create a button as a child NSView of the current component's window, make sure it's visible etc, and then mouse over it. What you'll see is that it may temporarily flash to the highlighted isOver state, it will immediately revert to not being highlighted, as if the mouse exited it (even though it didn't).
I have debugged this fairly extensively, and I can explain the problem, and I have a possible solution but it needs to be vetted by someone who understands this stuff more than I do.
The problem is in:
lib/JUCE/modules/juce_gui_basics/native/juce_NSViewComponentPeer_mac.mm
What's happening is that both the parent and the child NSView that JUCE creates have NSTrackingAreas installed. These areas are firing mouse events for both the parent and child windows when the mouse is over the child window (despite the NSTrackingInVisibleRect option being set -- it does not prevent this).
Now for methods like redirectMouseEnter() and redirectMouseExit(), this is handled properly by checking that the NSEvent's tracking area is actually the one installed for the current component's NSView.
But for the redirectMouseMove() method, that's not possible as [ev trackingArea] is not defined for this type of event. So what happens is the isWindowAtPoint() method returns true for both the parent and child windows, and they BOTH call sendMouseEvent(), leading to the current component changing repeatedly as the mouse moves. When the current component changes, JUCE calls mouseExit() for the previous component. It so happens that redirectMouseMove() is called in the order of child, then parent, so the button gets exited over and over as JUCE sees the mouseMove in the parent.
My proposed solution is to check if the top-level view at the mouse coordinates is, in fact, the view associated with the NSViewComponentPeer object on which redirectMouseMove() is called. So instead of:
It would be:
This solution does indeed fix things for my test case. But perhaps it causes issues I'm not aware of, or is not general enough, I'm not sure (which is why I didn't submit a pull request).
What is the expected behaviour?
Mousing over the TextButton in the example above should cause it to be highlighted in the isOver state until the mouse is moved out of the bounds of the button.
Operating systems
macOS
What versions of the operating systems?
Sonoma
Architectures
ARM, 64-bit
Stacktrace
No response
Plug-in formats (if applicable)
No response
Plug-in host applications (DAWs) (if applicable)
No response
Testing on the
develop
branchThe bug is present on the
develop
branchCode of Conduct
The text was updated successfully, but these errors were encountered: