setInterceptsMouseClicks to disallow clicks on children?

Hi,

I want to use setInterceptsMouseClicks, in order to disallow clicks on child components. Is that possible?

To be specific:
I have a parent component, which contains a slider. In the parent component I set
setInterceptsMouseClicks(true, false)
In other words: clicks on this component are allowed, but not on child components (the second boolean parameter is for allowClicksOnChildComponents, which I set to false).

But I still can click on the slider an modify it. So clicks on the children are still working.

I guess, I am using setInterceptsMouseClicks the wrong way?
Is there a way, to prevent child components from getting mouse clicks? Without telling each child separately to ingore mouse clicks?

I am asking, because I want to forward mouse clicks manually to the children. Before forwarding them, I want to run certain actions first.

I believe the click moves the other way - it is received first by the child and then goes up the chain.

Not really, the click is received from the ComponentPeer, and it will traverse via Component::hitTest(), until it finds the Component in the most specific leaf of the hierarchy.
The flag from setInterceptMouseClicks is used in hitTest:

If you have problems here, it might be worth to point out, that the parent is not, where the Component is a class member of, but rather, on which class you called addAndMakeVisible (child). Maybe this is the culprit?

Hi Daniel,

well, what I am doing is this:
I created a fresh project from the projucer. Then I just add a slider to the MainComponent, nothing else. I am using this code:

MainComponent::MainComponent()
{
    setSize (600, 400);
    addAndMakeVisible(slider);
    setInterceptsMouseClicks(true, false);
}

void MainComponent::resized()
{
    // This is called when the MainComponent is resized.
    // If you add any child components, this is where you should
    // update their positions.
    
    slider.setBounds(50,50,150,100);
}

As you can see, I added three lines to the CPP file, which the Projucer created:

addAndMakeVisible(slider);
setInterceptsMouseClicks(true, false);

and

slider.setBounds(50,50,150,100);

The result is: I can click on the child slider component, even though I disabled clicks on children in the call to setInterceptsMouseClicks().

But I think: I might be using setInterceptsMouseClicks() in the wrong way. It is probably not made for what I want it to do :slight_smile:

My understanding was, that the event traversal is steered by calling hitTest(). However, there are two internal methods, Component::contains(), which calls hitTest and would behave as we both expected it, but then there is reallyContains(), which ignores the interceptMouseClicks flags.

Now the methods isMouseOver(), isMouseDown() etc. ignore the hierarchy of components, but rather use the MouseSource::getComponentUnderMouse()

I am not sure if that is by design or by accident, that the interceptsMouseClicks() is now circumvented.

I just spent 3 hours naively believing that setInterceptsMouseClicks(true, false) would actually prevent child components from receiving mouse clicks, like the name suggests.
Turns out, if the child is something like a button, it still gets the clicks anyway. Very logical.
And of course, there’s nothing in the documentation to clarify this behavior.

I see plenty of real-world scenarios where you’d want to block clicks on all children, buttons included. But I can’t think of a single case where you’d use setInterceptsMouseClicks(true, false) to let buttons still work but block everything else.
If there’s a logic behind that behavior, I’d love to hear it.

Oh, and don’t believe you can get away with disabling children one by one — they still catch mouse clicks.
Lol.
No, you have to call setInterceptsMouseClicks(true, false) on each of them individually. That makes absolutely no sense.

1 Like