mouseWheelMove on viewported viewport


#1

Hi !

I think I have found a little problem with Component::mouseWheelMove.

I have a juce::Component hierarchy with juce::Viewport owning some Component owning themselves other juce::Viewport.
Some juce::Component in this hierarchy use addMouseListener method.

When I use the mouse wheel in the nested Viewport, scrollbars of the nested Viewport move at same time as the top Viewport.
It’s very disturbing during for the user experience.

This issue seem to come form the actual Component::mouseWheelMove default implementation:

void Component::mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& wheel) { // the base class just passes this event up to its parent.. if (parentComponent != nullptr) parentComponent->mouseWheelMove (e.getEventRelativeTo (parentComponent), wheel); }

I think the correct implementation should be:

void Component::mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& wheel) { // the base class just passes this event up to its parent.. if (parentComponent != nullptr && e.eventComponent == this) // passes only if it's not a listening event parentComponent->mouseWheelMove (e.getEventRelativeTo (parentComponent), wheel); }

Hope this can help !
Thanks in advance for your interest on this post.


#2

Interesting problem! But your suggestion could easily break existing code in subtle ways, so wouldn’t be a possibility.

Just to get it straight: There’s no problem unless you start calling addMouseListener on components, right? Seems like it’s not really the fault of the viewport if you arrange things so that it gets messages that it wasn’t expecting (?)


#3

Yes it’s not the fault of the Viewport.
Yes, If I comment all calls to addMouseListener in my project, there is no more issue.

You are right, my change can “break” existing code in subtle ways:
After this, some Component who have never call addMouseListener do not receive unexpected mouseWheelMove messages.
(previously forwarded by children who call addMouseListener on other Component hierarchy)
I think it’s a standard behavior who could be easily modified by an explicit addMouseListener call.

Without this change Juce has this strange behaviour:
When a Component calls chilren->addMouseListener(this…), he must override mouseWheelMove() to avoid some side effects.
(like forwarding unexpected mouse wheel message to potential parent Viewport)

I understand that compatibility rules are more important than this little issue,
I can use your workaround.
Perhaps this case just need to be documented…

Thanks again.


#4

I’m not 100% sure I understand your exact problem, but if you let me know what you think I should say in the documentation that would have helped, then I’ll add it!


#5

Hum, my English is not very well in the end of day, sorry for that, lets try something like that:

[code]
/** Called when the mouse-wheel is moved.

    This callback is sent to the component that the mouse is over when the
    wheel is moved.

    If not overridden, a component will forward this message to its parent, so
    that parent components can collect mouse-wheel messages that happen to
    child components which aren't interested in them.

    <New>
    Take care that if your component is used as a newListener of addMouseListener()
    It will forward the listened component mouse-wheel messages to its own parent.
    Even if listened component is interested to this mouse-wheel messages or not.
    <New/>

    @param event   details about the mouse event
    @param wheel   details about the mouse wheel movement
*/
virtual void mouseWheelMove (const MouseEvent& event,
                             const MouseWheelDetails& wheel);[/code]

hope that is more understandable


#6

Gotcha.