<html xmlns:v="urn:schemas-microsoft-com:vml" 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=Windows-1252">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<!--[if !mso]><style>v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style><![endif]--><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:"Yu Gothic";
        panose-1:2 11 4 0 0 0 0 0 0 0;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 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;}
@font-face
        {font-family:"\@Yu Gothic";
        panose-1:2 11 4 0 0 0 0 0 0 0;}
@font-face
        {font-family:"Iosevka Fixed SS16 ";
        panose-1:2 0 5 9 3 0 0 0 0 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        font-size:10.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
span.EmailStyle20
        {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><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</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"">Filters: are we talking about key bindings or event handlers?  With the key bindings, the user mappings take precedence over those registered through behavior.  There is no
 provision for adjusting priority of the event handlers – that’s the FX reality, we don’t get to rearrange event handlers within the node.  That’s why I mentioned event filters added
<u>to the control</u>.  I am not sure why you talk about HBoxes – adding a filter on the control enables the user to intercept the event prior to skin/behavior.<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"">So yes, this proposal does not address the event handlers (sorry for confusing key bindings with event handlers).  Unless we add addListenerBefore() API, we’d need to use event
 filters – but this is out of scope for this proposal.<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 do agree with you that we should keep the concrete Behaviors private for now.  In any case, public behaviors are outside of scope for this proposal.<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"">One thing you mentioned several times is a “truly good design”.  Let’s hear it!  Could you give us an outline, at the public API level at least, of such a design?<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"">Thank you<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 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">John Hendrikx <john.hendrikx@gmail.com><br>
<b>Date: </b>Thursday, October 12, 2023 at 01:33<br>
<b>To: </b>Andy Goryachev <andy.goryachev@oracle.com>, openjfx-dev@openjdk.org <openjfx-dev@openjdk.org><br>
<b>Subject: </b>[External] : Re: [Request for Comments] Behavior / InputMap<o:p></o:p></span></p>
</div>
<p><o:p> </o:p></p>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">On 11/10/2023 19:44, Andy Goryachev wrote:<o:p></o:p></span></p>
</div>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 "">Dear John:</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 ""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 "">Seems like addEventFilter() was specifically designed to intercept events before any other handlers, so I see no problem there.</span><o:p></o:p></p>
</blockquote>
<p>This is a misunderstanding of what filters are for.  They're called in the capturing phase and they can prevent an event from reaching its intended target, but you want it to reach the intended target FIRST, as you still want to give the target the chance
 to be the first to act upon the event.  For example, let's say I want to attach a function to the SPACE key in some specialized HBox, it should only do something when something closer to the target doesn't need it first (like a nested HBox of the same type,
 or an active TextField that uses SPACE for input).  Now if HBox had some FX default event handler that consumed SPACE, I have no options to override SPACE anymore; the filter is not a good spot, as its too early, and the handler is not a good spot because
 Behavior handlers were added before mine was.<o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt"><br>
<br>
<o:p></o:p></span></p>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 ""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 "">I somewhat disagree about the purpose of the key mapping system – the proposed solution solves two existing issues (the skin/behavior mappings and the user mappings) in one
 neat package.  Every other instrument such as addEventHandler/Filter is still there.</span><o:p></o:p></p>
</blockquote>
<p>I'm saying that the need for this would be almost non-existent if user event handlers weren't considered less important than FX ones. You have to be careful that there aren't two ways of doing things here:<o:p></o:p></p>
<p>If the event you wish to give an alternative purpose to is unused by FX, you can use an event handler; otherwise you must disable it (so you can use an event handler!) or remap it (using an alternative system).  Note that if FX at some point decides to "claim"
 another mapping, that would be a breaking change as some user event handlers may cease to function.<o:p></o:p></p>
<p>This is why I think the input mapping system should stay hidden; its an implementation detail of the Event handlers added by FX so they don't need to write long if/else/switch chains, and so they can more easily switch out mappings depending on state.  Opening
 up the input map effectively is being able to influence those FX added event handlers to do something different, while there is a perfectly good way of doing that already: add your own event handler (with higher priority).<o:p></o:p></p>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 ""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 "">And, if we look at the three bullet points</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 ""> </span><o:p></o:p></p>
<p style="margin-left:.5in">- Ensure user event handlers have priority over behavior/inputmap added ones<br>
- Ensure all behavior actions are available as methods on controls<br>
- Ensure that if a key is handled by the control, that it is ONLY consumed when it actually triggers an action (navigation keys get consumed regardless, even if no focus change results, that's wrong).<o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 "">I absolutely agree, and in fact the first three are indeed a part of the proposal.  Well, the 3<sup>rd</sup> one might unfortunately be a subject of backward compatibility
 limitation since one of the requirements was no behavior change w.r.t. the earlier versions.  We can always change the behavior if we have a completing reason and go through the usual process, nothing in the proposal precludes that.</span><o:p></o:p></p>
</blockquote>
<p>I don't see how your proposal addresses the first point.  <o:p></o:p></p>
<p>I've been reading the comments attached to <a href="https://bugs.openjdk.org/browse/JDK-8091189">
https://bugs.openjdk.org/browse/JDK-8091189</a> and it has a lot of good information, and raises many good points (immutable input maps, keep input maps/behaviors as implementation details, use interfaces instead of base classes, what about controls that have
 no Skin, even the point I made about having the Control be in charge of registering the event handlers instead of letting InputMap do it requiring a Control field...).  There are several patches by Jonathan Giles, and there is even a library created by the
 author of ReactFX that allows for replacing key bindings with a much nicer API already (in so far that is possible without having inside FX support). 
<o:p></o:p></p>
<p>The general tone of the comments seems to be that Behaviors should be kept as implementation details -- they're not well defined (what is a Behavior, what should be in the Behavior, what should be in the Skin and what should be in the Control) and until
 that is absolutely clear, exposing any of that as API is premature.  <o:p></o:p></p>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 ""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 "">Making the behaviors completely independent with setBehavior() and FXML, as you said, might be a future effort, perhaps we could attempt opening up certain controls at some
 point.  On one hand, I am for increasing the extensibility of FX, on the other hand the same argument can be made against it (as in solidifying a particular way of constructing skins and behaviors), but I feel it’s a separate issue that is independent of this
 proposal.</span><o:p></o:p></p>
</blockquote>
<p>I'm starting to lean towards keeping all of this as implementation details, at least until the current implementation is much cleaner than it is currently (the way InputMap and Behaviors currently are set up is more pragmatic than truly a good design), and
 just address the main issue: JavaFX stealing events that users want to override, note that I say events, key bindings are only part of it.<o:p></o:p></p>
<p>--John<o:p></o:p></p>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 ""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 ""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 "">-andy</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 ""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 ""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 ""> </span><o:p></o:p></p>
<div id="mail-editor-reference-message-container">
<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 <a href="mailto:openjfx-dev-retn@openjdk.org">
<openjfx-dev-retn@openjdk.org></a> on behalf of John Hendrikx <a href="mailto:john.hendrikx@gmail.com">
<john.hendrikx@gmail.com></a><br>
<b>Date: </b>Wednesday, October 11, 2023 at 01:04<br>
<b>To: </b><a href="mailto:openjfx-dev@openjdk.org">openjfx-dev@openjdk.org</a> <a href="mailto:openjfx-dev@openjdk.org">
<openjfx-dev@openjdk.org></a><br>
<b>Subject: </b>Re: [Request for Comments] Behavior / InputMap</span><o:p></o:p></p>
</div>
<p>I'm sorry, but that providing an arbitrary key mapping system seems completely out of scope and not something that JavaFX should concern itself with.  It's much too high level, when the key mappings involved should only be for actions that the control can
 provide on its own.<o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt">I think the problem we should be solving is that JavaFX control behaviors shouldn't be first in line when it comes to consuming events (which currently is only the case due to event handlers being added at
 the earliest possible opportunity, and event handlers being called in order).  If something as trivial as:
</span><o:p></o:p></p>
<p>       control.addEventHandler(KeyEvent.KEY_PRESSED, e -> {<br>
              if (e.getCode() == KeyCode.LEFT) {<br>
                    e.consume();  // stop default behavior<br>
              }<br>
       });<o:p></o:p></p>
<p>... actually worked, then there is much less need to redefine/disable behavior key mappings, and no need for a secondary system that deals with mappings (the first system, event handlers, can simply be used for this).  If user event handlers had priority
 over behavior ones, then everything you want can be achieved with the above, including:<o:p></o:p></p>
<p>- Stopping default behavior<br>
- Triggering different behavior (just call something on control, of course, make sure all behavior actions are available on the control in the first place)<br>
- Remapping (a combination of the above two)<br>
- Adding an alternative key for the same behavior<o:p></o:p></p>
<p>A system to remap keys can then be left squarely in the realm of user space, and much nicer solutions can be build by users than whatever JavaFX will provide out of the box.<o:p></o:p></p>
<p>Changes to the Behavior system can then focus on replacing complete behaviors (including their input map) and being able to use these by default for a certain subset of controls (like -fx-skin provide in CSS), as this is something users currently can't do.<o:p></o:p></p>
<p>So in short, what I think this should be about is:<o:p></o:p></p>
<p>- Ensure user event handlers have priority over behavior/inputmap added ones<br>
- Ensure all behavior actions are available as methods on controls<br>
- Ensure that if a key is handled by the control, that it is ONLY consumed when it actually triggers an action (navigation keys get consumed regardless, even if no focus change results, that's wrong).<o:p></o:p></p>
<p>Future:<o:p></o:p></p>
<p>- Make behaviors public and allow Behaviors to be replaced with -fx-behavior type CSS syntax / control.setBehavior calls<o:p></o:p></p>
<p>--John<o:p></o:p></p>
<p> <o:p></o:p></p>
<p>The focus should be on being able to modify standard behavior of controls (arrow-left, enter, ctrl-shift-right, etc.), specifically also to be able to disable these when undesired, and, on top of that, that they bubble up when NOT used even when they are
 configured (focus navigation keys currently are always consumed, whether they actually do something or not -- that's a big issue).  The other focus should be on providing an alternative behavior (or at least mappings) for all controls of a certain type --
 I don't see the need for adding a mapping to a specific control, that's already covered with event handlers; the problem is mostly that behaviors currently steal certain events before the user can get at them.<o:p></o:p></p>
<p>Custom behaviors can then be constructed that provide more things that may need mapping.  I'd expect those however to be limited in scope to what the control offers, certainly not an arbitrary key/action mapping system (that wouldn't even work, as most of
 these would be in the scope of several controls or be global).  This kind of functionality is much better provided by event handlers at the correct level for a group of controls, and I wouldn't expect to find such an eloborate system incorporated in behaviors.<o:p></o:p></p>
<p>In fact, thinking about all of this a bit more, <o:p></o:p></p>
<p> <o:p></o:p></p>
<p>On 10/10/2023 19:54, Andy Goryachev wrote:<o:p></o:p></p>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 "">Re-sending with a smaller image (256kb limit, really?).</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 ""> </span><o:p></o:p></p>
<div id="mail-editor-reference-message-container">
<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">Andy Goryachev <a href="mailto:andy.goryachev@oracle.com">
<andy.goryachev@oracle.com></a><br>
<b>Date: </b>Tuesday, October 10, 2023 at 10:49<br>
<b>To: </b>Michael Strauß <a href="mailto:michaelstrau2@gmail.com"><michaelstrau2@gmail.com></a><br>
<b>Cc: </b><a href="mailto:openjfx-dev@openjdk.org">openjfx-dev@openjdk.org</a> <a href="mailto:openjfx-dev@openjdk.org">
<openjfx-dev@openjdk.org></a><br>
<b>Subject: </b>Re: [Request for Comments] Behavior / InputMap</span><o:p></o:p></p>
</div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 "">Dear Michael:</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 ""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 "">Here is a use case for (re-)mapping by the user at runtime:</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 ""> </span><o:p></o:p></p>
<p class="MsoNormal"><img border="0" width="773" height="656" style="width:8.052in;height:6.8333in" id="Picture_x0020_2" src="cid:part1.Mz2XogCD.DoK2QaIf@gmail.com"><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 ""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 "">(key mappings UI in Eclipse).</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 ""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 "">I can think of several other cases (mentioned in the proposal, I think) so I think we can put the concept of immutable or global InputMap to rest.</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 ""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 "">Whether the InputMap contains the reference to its control or not is a minor implementation detail, I think.</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 ""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 "">-andy</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 ""> </span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Iosevka Fixed SS16 ""> </span><o:p></o:p></p>
<div id="mail-editor-reference-message-container">
<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 <a href="mailto:openjfx-dev-retn@openjdk.org">
<openjfx-dev-retn@openjdk.org></a> on behalf of Michael Strauß <a href="mailto:michaelstrau2@gmail.com">
<michaelstrau2@gmail.com></a><br>
<b>Date: </b>Tuesday, October 10, 2023 at 10:36<br>
<b>To: </b><br>
<b>Cc: </b><a href="mailto:openjfx-dev@openjdk.org">openjfx-dev@openjdk.org</a> <a href="mailto:openjfx-dev@openjdk.org">
<openjfx-dev@openjdk.org></a><br>
<b>Subject: </b>Re: [Request for Comments] Behavior / InputMap</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">> Yes, one of the features the new design provides is ability to modify key mappings by the user at runtime.  So yes, not only it needs to be mutable, but it also adds some APIs for exactly that.<br>
><br>
<br>
I struggle to see a use case for this feature. I can imagine that<br>
there might be some use cases that call for customized input mappings,<br>
but why would this translate to a _mutable_ input map? That's quite a<br>
departure from the way other parts of JavaFX work.<br>
<br>
For example, skins are also immutable. If you want to have a different<br>
skin for a control, you don't somehow modify the existing skin<br>
instance; instead, you'd create a new skin class (or -- somehow --<br>
extend an existing skin class), and then install that new skin on your<br>
control.<br>
<br>
An input map shouldn't bind input events directly to instance methods<br>
of a particular control instance. It should define the mapping of<br>
events to methods symbolically:<br>
<br>
Instead of mapping Event => instance.method(), it should map Event =><br>
Control::method. The input map could then be stateless and immutable,<br>
and can be set on any control instance. If you want to change the<br>
mappings, just set a different input map instance. There's no need<br>
that an input map would retain a reference to any particular control,<br>
since the control reference can be passed into the input map just as<br>
easily.</span><o:p></o:p></p>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</body>
</html>