Mouse click triggers twice for parent

First of all, here is my code:

Parent constructor:

    addMouseListener(this, true);

and then still in parent:

   if (event.mouseWasClicked()) {
	if (event.mods == juce::ModifierKeys::rightButtonModifier) {
             if (event.eventComponent == this) {
                      // Do-stuff
             }
        }
   }

What I know:
Since I pass true in addMouseListener(), parent will also receive mouseevents for child components.

What I expected:
Mouse event triggers once for the parent component and once for the child component.

What actually happens and confuses me:
Mouse event triggers twice just for the parent and once for the child.

Obvious question:
What causes this behavior and how can I “fix” it?

The Component class is already a MouseListener so when you call addMouseListener() in your parent component you’re adding it twice, hence the two mouse events. Just override the virtual mouseDown/Up/Drag etc. methods of Component to be notified of mouse events inside the parent. If you want to know about mouse events in a child component then you can add your parent as a MouseListener to the child component by calling addMouseListener() on it.

Ed

Hey,
digging up this topic,
I’m having the same problem and can’t find an easy solution to just get events from the component itself and for it’s children as well :
if do addMouseListener(this, true), it will get the children events but will run mouseDown() twice (for instance) clicking on the component itself, one from the component and one from the listener.
the problem is there is no way to disable the default sending, or just specify without adding a mouseListener that we are interested in children.
the setInterceptMouseClicks(true, true) doesn’t seem to do the trick either…

As I have a lot of children to add / remove, I don’t want to resolve to adding manually a listener to each child

any clue ?
Thanks

It does, if used right. If you call setInterceptMouseClicks (true, false); on the parent, you will get also the children’s mouse events of the children, since it doesn’t try to find a child to forward the event to.
The only drawback is, you also don’t get mouseEnter and mouseExit events on the children, if you were interested in those.

Thank you for this fast reply !
Yes I actually need 2 things that I don’t think i will get with setInterceptsMouseClicks(true, false):

  • Like you said, I need child components to still be able to receive those events
  • I need to be able to know which component has been clicked in the parent component’s event callback.

I actually pushed a Pull Request that adds new flag to the component, to be able to disable the default mouse event : https://github.com/WeAreROLI/JUCE/pull/559

Another way would be to have a flag “receiveChildMouseEvents”, which would allow to not have to add a listener to itself.

Well, if you actually want the mouse to react in two components, a MouseListener is appropriate.

The MouseEvent has a member originalComponent, so you can find out, on which of the children your event actually occurred.

Yes, all of that is already implemented but the when the originalComponent is also the eventComponent (i.e. the parent component in this case), then the 2 events triggered when clicking on this component have exactly the same MouseEvent argument provided, with originalComponent and eventComponent set to it, so there is no way to actually differenciate an event from the MouseListener or an event from the internal working of the Component class.
Hence my mod to disable the internal event triggering and have a clean feedback.
I’m honestly suprised that there are not more people needing this behavior, it seems kinda standard to need to have bubbling events from children to parents and be able to catch those events from the children at the same time…

Hi All (especially the Juce team),
There are a many conversation threads I could post this question on. I have not found a simple hack. It appears unsafe to attach a mouse listener from a MultiDocumentPanelWindow resizer into the MultiDocumentPanelWindow constructor. Is the following a viable solution for listening to children from a parent component or will it cause problems? In the code proposed I am deleting the Component class listener and then re-adding it with wantsEventsForAllNestedChildComponents flagged as true.
Thank you

SomeMultiDocumentPanelWindowClass ()
{
  removeMouseListener (this);
  addMouseListener (this, true);
}
void mouseDown (const juce::MouseEvent& e) override
{
  if (
      e.originalComponent==SomeMultiDocumentPanelWindowClass::resizableBorder.get()
      ||
      e.originalComponent==SomeMultiDocumentPanelWindowClass::resizableCorner.get()
      )
  {
    DBG("hit resizer");
  }
  else if (e.eventComponent == this)
  {
    DBG("hit parent");
  }
}
, etc