I am not sure this is the best solution, since it does not solve the problem of multiple actors adding their event handlers. I do like the idea of prioritized event handlers, because it solves the problem *reliably*.
I think there is no way around it - we need different priorities. It may be a set or may be a wide range of integers (for the maximum flexibility), but the main idea is that, at least in controls, we have a situation where there are at least these priorities: - application event filters - application event handlers - event handlers set by the skin - ifUnconsumed-like handlers set by the skin - ifUnconsumed-like handlers set by the application Please refer to the table in the "InputMap" section in this document: https://github.com/andy-goryachev-oracle/Test/blob/main/doc/InputMap/InputMapV3.md (it has more levels due to the desire to define additional levels specific for key mappings, but it's the same idea). Now, this was proposed in assumption that we only have this problem at the controls level. I've asked for any examples that suggest otherwise, so far received none, but let's wait a bit more. My point is that prioritized event handlers solve the issue reliably. Whether this is implemented in an FX-wide manner, or via the InputMap is less important at this stage. At this stage, I think it's more important to eliminate the approaches that are guaranteed not to work, and outline the ideas that might work. What do you think? -andy From: openjfx-dev <openjfx-dev-r...@openjdk.org> on behalf of Michael Strauß <michaelstr...@gmail.com> Date: Saturday, November 9, 2024 at 23:13 To: openjfx-dev <openjfx-dev@openjdk.org> Subject: Unconsumed event handlers 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