Re: Mouse Button Modifiers Lost In Newt mouseDragged Events
Posted by rhatcher on Oct 12, 2012; 8:17pm
URL: https://forum.jogamp.org/Mouse-Button-Modifiers-Lost-In-Newt-mouseDragged-Events-tp4026456p4026484.html
> Well, my intuition would say 'yes the pressed button information
> should be delivered with the MouseEvent.EVENT_MOUSE_DRAGGED event.
Yes - one has to believe that it's common to want to know what the current button state is for any event, including dragging. At least I want to know it :-).
> WindowImpl.java line 2061:
> e = new MouseEvent(MouseEvent.EVENT_MOUSE_DRAGGED, this, when,
> modifiers, x, y, 1, mouseButtonPressed, 0);
>
> This shows how we actually synthesize the _native_ mouse-drag-event.
> Only this way we are able to harmonize the dragging in NEWT for
> all platforms.
WindowImpl does something slightly different from the AWT, which gets into the issue of preserving (or not) the semantics of similarly named methods.
As we have mentioned before though, we shouldn't do wrong things just because the AWT is doing wrong things, but in this case I'm not sure which one is wrong.
As we mentioned earlier, the AWT event's getButton() method says it returns the button that changed. The current comprehensive button state is also available in the event's modifiers and extended modifiers, so all information about button state is still available. My observation so far is that a lot of the time AWT's getButton() method returns 0, which is consistent with the associated javadocs. I guess the getButton() method was intended to be a convenience to keep the user from having to track historical button state themselves and compare to current button state to figure out what changed. For example, if I set up some listeners to watch some of this stuff and dump out modifier bits I'll see something like this when a click-and-drag is initiated:
...
AWT mouse moved, mods = 0, mods ex = 0, button = 0
AWT mouse pressed, mods = 10000, mods ex = 10000000000, button = 1
AWT mouse dragged, mods = 10000, mods ex = 10000000000, button = 0
...
The getButton() method returns a 1 on the press, but then for the drag it's returning 0. I guess for mouse moved the getButton() result would always be 0 anyway because if a button is pressed then it's a mouse drag, not a mouse move.
The pattern above is similar if buttons 2 and 3 are used instead, the only difference being which button is returned by getButton() for the mousePressed event that initiates the drag.
If a second button is pressed while the button used to initiate the drag operation is still down, then a mousePressed event will show up in the middle of the mouseDragged events and getButton() will return the additional button that was pressed:
...
AWT mouse dragged, mods = 10000, mods ex = 10000000000, button = 0
AWT mouse pressed, mods = 1000, mods ex = 110000000000, button = 2
AWT mouse dragged, mods = 11000, mods ex = 110000000000, button = 0
...
If the second button pressed is then released then a released event shows up, but the drag events continue:
...
AWT mouse dragged, mods = 11000, mods ex = 110000000000, button = 0
AWT mouse released, mods = 1000, mods ex = 10000000000, button = 2
AWT mouse dragged, mods = 10000, mods ex = 10000000000, button = 0
...
What WindowImpl is doing - at least for mouse dragged events - is always returning the button that was most recently pressed from getButton() during dragging.
So there is still a question here of the semantics of getButton() for NEWT - is it intended to indicate the button that changed, or indicate current button state? The modifiers already tell the comprehensive story of button state - or at least they will after we fix the bug that started this discussion - and in NEWT's case we also have getButtonsDown() and isButtonDown(someButton) to provide this information. So... maybe NEWT's getButton() should follow the semantics of the AWT (keep in mind that when I say this I am not promoting AWT's behavior as being the correct behavior). Or... deprecate getButton() and eventually eliminate it altogether, and make the user figure out what buttons changed.
I noticed another oddity while I was looking at this: in the case above where a drag is initiated then a second button is pressed and released while the button that initiated the drag remains held down, the AWT will continue to send mouse dragged events following the release of the second button, but WindowImpl will lose the drag state and start sending mouse moved events after the second button is released even if the button that initiated the drag remains held.
This probably is another bug. However, it highlights the question again of what NEWT's semantics should be. Should this remain a series of drag events after the second button is released? I think so if the button that initiated the drag remains held.
> Maybe we can do the same for the AWT->NEWT event factory, i.e. properly track
> the mouse states. One thing comes to mind now is the fact that we follow 2 path
> for key/mouse events.
> 1) Native delivery of details via WindowImpl.doMouseEvent()
> 2) TK -> NEWT factory, which creates event itself and queues them
>
> (1) does simple state tracking and synthesizes missing event etc
> (2) does this not properly and is a diff. code path
>
> Maybe we can change our factories (2) in a way to use method (1),
> so it follows same path. What do you think ?
> Then we can at least assure (better) that native events
> and translated events behave similar.
Your option 1 above sounds like a much better approach: back up to more primitive concepts that all the underlying toolkits can agree on, and reconstruct your own semantics from there. It will insulate NEWT from the oddities of the various toolkits. Though... I don't have broad enough platform exposure past Linux (Mac, Android, etc) at the moment to know where difficulties might lie, especially in the multi-touch world.
FYI I got set up on github this morning and forked the repos under sgothel/jogl etc. I've sync'd those down to my local box and was going to make the bug fix for mouse button state there and push it back up to github. I guess then I have to create a pull request. Please bear with me on this; I'm a total git noob and am "drinking from a fire hose" at the moment, so I'm not quite sure what I'm doing yet particularly in the "best practices" area. Any recommendations about the best way to handle this current bug fix would be welcome.