Generate or pass on a mouse event


#1

Hi,

I have a “host” component that contains a child component. the host component elects to receive all the mouse events. This is so i can do tricky things at the host component level. Sometimes i want to pass on the mouse event. Is there either a way to re-dispatch/pass on/or regenerate a mouse event, does anyone know?

i thought i could simply get away with calling the child component `mouseDown’ etc. but this bypasses any additional mouse listeners registered.

thanks for any tips.


#2

Can Component::setInterceptsMouseClicks() be of any use to you?


#3

thanks for your suggestion.

That’s what im doing now. I’ve got a kind of editor in which you can move components. The editor is a container and when you click on a component inside the editor, i want the editor to receive the event. This is because the editor can decide to handle the mouse event for its own move and placement purposes. When it does this, i dont want the mouse events to also go to the component inside (otherwise i could just add a mouselistner on the editor). I achieve this by `setInterceptsMouseClicks(false, false)’ on the inside components.

However, sometimes i need to propagate the mouse event through. This is when the editor decides the event is something for the component. Originally i just called `mouseDown’ etc to pass it on. However, this bypasses a lot of other handy juce stuff.

I’ve managed to achieve the result I want by calling `internalMouseDown’ but this is actually a private method of the Component. hm.


#4

I’ve always dealt with these sorts of problems from the bottom up. So all your child components always receive their intended mouse events but they have various flags which tell them what to do with them. If they are in a non-moveable mode they simply transfer them to the parent using MouseEvent::getEventRelativeTo.

You could go one step further with this and have the container then set the flags on the child whilst it’s still inside it’s mouse callback. When control returns to the child it then should know what to do with the event, if anything. Of course you’ll have to be careful about the order in which these things happen but might be more viable than calling private methods.


#5

There’s no way to catch and then re-send a mouse event, because the event system needs to be able to make sure down/drag/up events arrive at each comp in the correct order. But something I’ll be doing soon will be to add some kind of system for intercepting events, so that you can recognise gestures without needing every component to be gesture-aware. (I guess this is probably what hugh’s actually trying to do).


#6

How about if, when adding a mouse listener, you could control the order in which it is called. Like, er, “z-order” for events??.

For example, Dave’s suggestion could then be achieved by adding a mouse listener to each component indicated to be called before the native event. The handlers for these could set flags appropriately in the components.

Anyhow, i can run with my hacks as it is. At least this is not one of those cases where there’s a Juce one-liner that does it all for me :slight_smile:


#7

What I was thinking of doing was just adding a method that can steal the mouse input away from whatever currently has it. So you’d create a gesture recognising class which is a mouselistener, attach it wherever you like, snoop on the incoming events, and if it looks like a gesture, call the method to steal the input, which will send some kind of “cancel” event to whatever had been receiving the events.


#8

That idea sounds very good. the problem with multiple listeners is that you have to manage a bunch of states so that those not really interested in the event ignore it.

One of the things i’ve had trouble with is changing the ModifierKeys. my previous hack of calling the private internalMouseDown' method has now been abandoned. I did this because i had an additional MouseListener on my component. I later ran into a problem where i had to, effectively, turn mouseDown into a mouseUp. There was no way to convince the internal mouse source of this. So in the end, i rewrote a lot of my code to avoid needing a second MouseListener and now i call the componentmouseDown’ (etc) directly, as in my original approach. Naturally, this will only work in a limited way. There is still the problem, however, that I have to call mouseDown during the `mouseUp’ handler of a parent component.

MouseEvent de = e.getEventRelativeTo(c); // XXX Nasty HACK! ModifierKeys* kp = (ModifierKeys*)&de.mods; *kp = ModifierKeys(ModifierKeys::leftButtonModifier); _mouseRedirect->mouseDown(de);

All this comes about, as you’ve mentioned, when trying to integrate gestures and mouse events. Since gestures come through as mouse events, you get situations where you have to “translate” them. One of the things im trying to do is make an interface that works on both desktop and mobiles, so that something that might be a right mouse button on the desktop will be a gesture on the mobile, or perhaps activated by a long tap which then enters a state where i have to reinterpret subsequent mouse events.

Another annoyance is keyboard focus. Juce is designed to try to assign focus with clicks. However, on mobiles whenever there’s a keyboard focus, a giant keyboard pops and covers half the screen. This keyboard winds up flapping up and down in a comedy way as you touch things. So what i had to do is assign keyboard focus in a more specific way to components within my parent canvas. Its turns out the means to do this totally manually is possible in Juce, but you have to setMouseClickGrabsKeyboardFocus' to false, then managewantKeyboardFocus’ dynamically and call `grabKeyboardFocus’ as required. Unfortunately, there’s no way to discard the keyboard focus, so you have to have a bogus component to assign it to. So i’ve got the key focus sorted.


#9

Yes, it’s all a bit of a pain to support tablets! I’ve got a win8 tablet now though, so that’s a good testbed for this kind of thing, and I’ll be experimenting with gesture stuff as one of my next tasks…


#10

Hi, just wondering where things are at with this gesture type stuff... I'd like to pass through any mouseDrag events from things like labels and buttons so the user can do a swipe and move/dismiss the whole component. Currently works as long as the user does not happen to touch a chld component that consumes the mouseEvent. 

 


#11

Yeah, sorry, haven't had chance to get stuck into that yet!