<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Aptos;
        panose-1:2 11 0 4 2 2 2 2 2 4;}
@font-face
        {font-family:"Iosevka Fixed SS16";
        panose-1:2 0 5 9 3 0 0 0 0 4;}
@font-face
        {font-family:"Times New Roman \(Body CS\)";
        panose-1:2 11 6 4 2 2 2 2 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        font-size:10.0pt;
        font-family:"Aptos",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
span.EmailStyle19
        {mso-style-type:personal-reply;
        font-family:"Iosevka Fixed SS16";
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;
        mso-ligatures:none;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
--></style>
</head>
<body lang="EN-US" link="blue" vlink="purple" style="word-wrap:break-word">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">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 *<b>reliably</b>*.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">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:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">- application event filters<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">- application event handlers<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">- event handlers set by the skin<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">- ifUnconsumed-like handlers set by the skin<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">- ifUnconsumed-like handlers set by the application<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">Please refer to the table in the "InputMap" section in this document:<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><a href="https://github.com/andy-goryachev-oracle/Test/blob/main/doc/InputMap/InputMapV3.md">https://github.com/andy-goryachev-oracle/Test/blob/main/doc/InputMap/InputMapV3.md</a><o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">(it has more levels due to the desire to define additional levels specific for key mappings, but it's the same idea).<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">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.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">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.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">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.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">What do you think?<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16"">-andy<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16""><o:p> </o:p></span></p>
<div id="mail-editor-reference-message-container">
<div>
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal" style="margin-bottom:12.0pt"><b><span style="font-size:12.0pt;color:black">From:
</span></b><span style="font-size:12.0pt;color:black">openjfx-dev <openjfx-dev-retn@openjdk.org> on behalf of Michael Strauß <michaelstrau2@gmail.com><br>
<b>Date: </b>Saturday, November 9, 2024 at 23:13<br>
<b>To: </b>openjfx-dev <openjfx-dev@openjdk.org><br>
<b>Subject: </b>Unconsumed event handlers<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">In JavaFX, user code and skins share the same event system. Since<br>
invocation order is fundamentally important for events, this leads to<br>
a lot of problems when skins add event handlers to their controls.<br>
Assume user code adds an event handler to a control, and _then_ sets a<br>
skin that also adds an event handler for the same event. In this case,<br>
the user-provided handler is invoked first. If the skin is set<br>
_first_, the skin gets the first chance to handle the event (see also<br>
<a href="https://bugs.openjdk.org/browse/JDK-8231245)">https://bugs.openjdk.org/browse/JDK-8231245)</a>.<br>
<br>
Prioritized event handlers might be a solution for this problem, but<br>
they are quite difficult to get right. Instead, I think we can get<br>
almost all of the benefits using a much simpler solution: unconsumed<br>
event handlers.<br>
<br>
We add a new method to the `Event` class:<br>
<br>
    <E extends Event> void ifUnconsumed(EventHandler<E> handler)<br>
<br>
When an event filter or an event handler receives an event, it calls<br>
the `ifUnconsumed` method with another event handler. Then, after both<br>
phases of event delivery have completed, the list of unconsumed event<br>
handlers associated with the event is invoked in sequence. Once an<br>
unconsumed event handler consumes the event, further propagation is<br>
stopped.<br>
<br>
Skins and their behaviors would then always use the unconsumed form of<br>
event handlers:<br>
<br>
    // inside a skin/behavior<br>
    control.addEventHandler(<br>
        KeyEvent.KEY_PRESSED,<br>
        e -> e.ifUnconsumed(event -> {<br>
            // act on the event<br>
        }));<br>
<br>
This allows user code to see an event during both the capture and<br>
bubble phases without any inteference of the skin or behavior. If user<br>
code doesn't consume the event, the skin or behavior gets to act on<br>
it.<br>
<br>
In addition to that, we add a second new method to the `Event` class:<br>
<br>
    void discardUnconsumedEventHandlers()<br>
<br>
Calling this method in an event handler allows user code to discard<br>
any unconsumed event handlers that have been registered prior. Let's<br>
consider an example where user code wants to prevent a control skin<br>
from acting on the ENTER key event, but it also doesn't want to<br>
consume the event. Adding an event handler to the control, and then<br>
calling `discardUnconsumedEventHandlers()` inside of the event handler<br>
achieves exactly that: it allows the ENTER key event to flow freely<br>
through the control without interacting with it, since its unconsumed<br>
event handlers will never be called.<br>
<br>
Here is the PR for this proposal: <a href="https://github.com/openjdk/jfx/pull/1633">
https://github.com/openjdk/jfx/pull/1633</a><o:p></o:p></span></p>
</div>
</div>
</div>
</div>
</div>
</body>
</html>