MouseEvents and Lambdas

So, over in the thread about Signals and Slots here I said that it would be great if component::mouseDown() could be implemented this way:
component.mouseDown = []() { DBG("component mouseDown"); };

So, digging a little bit deeper into how mouse events are sent out from the mouseEventSource to the listeners, i ended up at this method:

static void sendMouseEvent (Component& comp, 
   Component::BailOutChecker& checker,
   void (MouseListener::*eventMethod) (const MouseEvent&), 
   const MouseEvent& e)

Is there a way to modify it so that the 3rd and 4th arguments could be a lambda instead or std::function? somethin’ like:

static void sendMouseEvent( Component& comp, Component::BailOutChecker& checker,
 std::function<void(const MouseEvent& e)> f );

I realize the tricky part is that the sendMouseEvent() function calls void (MouseListener::*eventMethod)(const MouseEvent& e) for every component that added themselves as a listener to this particular mouseEvent. Perhaps I am just requesting a pipe dream…
But it is 2017, juce5 is using C++11, so shouldn’t we be able to write easier to read code without writing massive if(button == &myButton) switches inside the buttonClicked() callback when our GUI has lots of buttons?

I began my search here for understanding how mouseEvents make their way to a component

void Component::internalMouseDown (MouseInputSource source, Point<float> relativePos, Time time, float pressure)

where a mouseDown(me) is called, followed by
MouseListenerList::sendMouseEvent (*this, checker, &MouseListener::mouseDown, me);


nothin? not a single response?

Now you have two likes :slight_smile:

@jules @fabian trying to get this request noticed!

Yeah, it’s a good request, but you could also roll your own implementation in a few lines of code without any changes to juce itself. Just create a class that inherits from MouseListener, and contains lambdas to call for each callback, then add that to your component, e.g.

struct MyComponent  : public Component
        addMouseListener (&invoker);
        invoker.mouseDown = [] (const MouseEvent&) { ...etc };

    MouseEventInvoker invoker;
1 Like

@jules wait.

how do you even override

virtual void mouseDown( const MouseEvent& event);

so it’s a

std::function<void( const MouseEvent& )> mouseDown;

in the inheriting class?!?!

@Jules can you show the MouseEventInvoker class you definitely teased and omitted in your example? PLEEEEEAAAASSSSEEE?!?!?!

This one works:

class Invoker : public MouseListener

    std::function<void(const MouseEvent&)> onMouseDown;

    void mouseDown (const MouseEvent& e) override
        if (onMouseDown) onMouseDown (e);

    addMouseListener (&invoker, true);

    invoker.onMouseDown = [](const MouseEvent& e) {
        DBG ("You clicked me: " << e.getPosition().toString());

    setSize (600, 400);

    Invoker invoker;

Addition: capture this:

    setComponentID ("Foo");
    addMouseListener (&invoker, true);

    WeakReference<Component> myself (this);
    invoker.onMouseDown = [myself](const MouseEvent& e) {
        if (myself) {
            DBG ("Hello I'm " << myself->getComponentID());
        DBG ("You clicked me: " << e.getPosition().toString());

Next step to have that templated for Invoker<Button> maybe?

Thanks Daniel, yep, that’s the idea!

(Sorry @matkatmusic, wasn’t trying to tease, just thought the implementation would be pretty obvious!)

@jules it wasn’t obvious!

Fair enough - I was assuming a certain level of fluency with lambdas, based on the fact that you were asking for them! :slight_smile: