hitTest ignore setInterceptsMouseClicks

Seems like in some situations, Components are totally ignoring setInterceptsMouseClicks() after hitTest() has been overridden.

example:

struct InnerComp : Component
{
    InnerComp()
    {
        setInterceptsMouseClicks(false, false);
    }

    void paint(Graphics& g) override
    {
        g.setColour(Colours::blue);
        g.fillRect(internal);
    }

    void mouseDown(const MouseEvent&) override { DBG("ChildClicked"); }
    bool hitTest(int x, int y) override { return internal.contains(x, y); }

    Rectangle<int> internal {20, 20, 100, 100};
};

struct MainComponent : Component
{
    MainComponent()
    {
        addAndMakeVisible(comp);
        setSize(600, 400);
    }

    void mouseDown(const MouseEvent&) override { DBG("Clicked parent"); }
    void resized() override { comp.setBounds(getLocalBounds()); }

    InnerComp comp;
};

While I can solve it locally by forcing the flag check in the super class:

    bool hitTest(int x, int y) override
    {
        return Component::hitTest(x, y) && internal.contains(x, y);
    }

This doesn’t scale, because in my real code I have reusable Components where I want the parent to decide if they’re clickable, and would rather avoid changing them, so this solution fails.

Any ideas?

idk if it’s the most elegant solution but you could put a lambda into hittest so that it only performs its operation if this component’s setIntercerpt is not false, else it returns false. (lambda because the actual operation might vary, idk)

I’m showing that in the thread:

    bool hitTest(int x, int y) override
    {
        return Component::hitTest(x, y) && internal.contains(x, y);
    }

If you look at the implementation of the base class function, it checks those flags. So it ‘works’.

But, for this system to work it has to check the flags for the parent, and going ‘down’ recursively.

For example, it’s possible this Component is defined as setInterceptsMouseClicks(true, true), but the parent is defined as setInterceptsMouseClicks(true, false).

In that case, I would expect the parent’s flags would ‘take over’ and not allow the children to get any events, regardless of their hit test. But JUCE seems to call hitTest() on the child anyway in this case, totally ignoring what the parent has set.

i see. i would expect this to depend on the sequence in which setInterceptsMouseClicks was called. if the parent called it first with (true,false) ofc juce would think all children don’t use incoming mouse events, but if you call (true, true) on a child after that some internal stuff might be overwritten back to that behaviour. maybe that’s why you experience this behaviour. have you tried setting the intercepts for the children first, yet?

The order doesn’t seem to make any difference.
Also IMO it shouldn’t make any difference, I should be able to have both orders in a dynamic system.

For example if I call setVisible(true) on a child, and the parent has setVisible(false) on it, the child should never be visible in any order of calls.