I've run into some problems while trying to make event handlers on skins only act when the event isn't consumed by user code. Consider a button that is nested in some hierarchy:
scene --> root ----> button When the button receives a MOUSE_RELEASED event, it consumes the event and fires off an ACTION event. Doing that in a default handler is fine, but as as consequence, the MOUSE_RELEASED event won't be immediately consumed. Instead, it bubbles up the entire hierarchy before it is finally handled and consumed by the button in its default handler after the dispatch chain has completed. This is clearly not what we want, as it can potentially cause ancestors to act on the event, too. (By the way, this also rules out an event system where events are dispatched in prioritized capture/bubble phases.) I think what we need is quite a bit simpler. Default event handlers are still the way to go, but they shouldn't act across the entire dispatch chain. Instead, they should only act locally on a single event target: when a target receives an event, it first invokes its regular handlers. Then, if the event is still eligible for default handling, the default handlers are invoked. Skins and behaviors should always use default handlers, never regular handlers. In the example, the button would consume the MOUSE_RELEASED event in its default handler, which will prevent it from bubbling up the hierarchy. If user code adds an event handler to the button, the user handler will always be invoked first and gets to decide whether to consume the event (Event.consume()), prevent the default handler from running (Event.preventDefault()), or let it continue to flow. Using this simplified model, I've been able to switch over InputMap and ListenerHelper (and therefore almost all controls) to use default handling, and it seems to work pretty well. Here is a PR with the implementation: https://github.com/openjdk/jfx/pull/2022
