In JavaFX, user code and skins share the same event system. Since invocation order is fundamentally important for events, this leads to a lot of problems when skins add event handlers to their controls. Assume user code adds an event handler to a control, and _then_ sets a skin that also adds an event handler for the same event. In this case, the user-provided handler is invoked first. If the skin is set _first_, the skin gets the first chance to handle the event (see also https://bugs.openjdk.org/browse/JDK-8231245).
Prioritized event handlers might be a solution for this problem, but they are quite difficult to get right. Instead, I think we can get almost all of the benefits using a much simpler solution: unconsumed event handlers. We add a new method to the `Event` class: <E extends Event> void ifUnconsumed(EventHandler<E> handler) When an event filter or an event handler receives an event, it calls the `ifUnconsumed` method with another event handler. Then, after both phases of event delivery have completed, the list of unconsumed event handlers associated with the event is invoked in sequence. Once an unconsumed event handler consumes the event, further propagation is stopped. Skins and their behaviors would then always use the unconsumed form of event handlers: // inside a skin/behavior control.addEventHandler( KeyEvent.KEY_PRESSED, e -> e.ifUnconsumed(event -> { // act on the event })); This allows user code to see an event during both the capture and bubble phases without any inteference of the skin or behavior. If user code doesn't consume the event, the skin or behavior gets to act on it. In addition to that, we add a second new method to the `Event` class: void discardUnconsumedEventHandlers() Calling this method in an event handler allows user code to discard any unconsumed event handlers that have been registered prior. Let's consider an example where user code wants to prevent a control skin from acting on the ENTER key event, but it also doesn't want to consume the event. Adding an event handler to the control, and then calling `discardUnconsumedEventHandlers()` inside of the event handler achieves exactly that: it allows the ENTER key event to flow freely through the control without interacting with it, since its unconsumed event handlers will never be called. Here is the PR for this proposal: https://github.com/openjdk/jfx/pull/1633