<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<p>Hi Andy,<br>
</p>
<div class="moz-cite-prefix">On 16/10/2023 21:43, Andy Goryachev
wrote:<br>
</div>
<blockquote type="cite"
cite="mid:DM5PR1001MB21727E4E85D417CE348AF751E5D7A@DM5PR1001MB2172.namprd10.prod.outlook.com">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<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-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;}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;}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]-->
<div class="WordSection1">
<p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed
SS16"">John,<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 understand this message was sent before the
one with an alternative proposal, so I’ll address those
parts that discuss the original input map one.<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"">Also, I suspect that the major redesign of FX is
highly unlikely - we simply don’t have the resources to do
that.<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 style="margin-left:.5in">I see BehaviorBase moving to a
public package though, and it is not package private, is that
intended then?<o:p></o:p></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"">Yes, the BehaviorBase is public for two reasons:<o:p></o:p></span></p>
<p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed
SS16"">1. to be used as a key for behavior-specific
mappings<o:p></o:p></span></p>
<p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed
SS16"">2. provide the second part of the InputMap APIs
intended for behaviors<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 is not the goal to make concrete behaviors
public at this time.</span></p>
</div>
</blockquote>
<p>My problem here is that by making this class public (which IMHO
is not a good design) will lock us out of improving this later. <br>
</p>
<p>Nothing Behavior related should be made public without a full
design of how Behaviors should work, what their responsibilities
are, how they interact with Skins (if at all, IMHO they
shouldn't), etc. Once a design is known and agreed upon, then we
can work on step-by-step improvements by making parts public, and
leaving parts hidden.<br>
</p>
<span style="font-size:11.0pt;font-family:"Iosevka Fixed
SS16""></span>
<p>We really need to think ahead here how Behaviors will work when
users are allowed to create their own in some future version of
FX, even if we don't want to put in the work right now to make it
possible.</p>
<p>The rest of this post is a similar pattern; API decisions are
IMHO being justified by existing choices, like Skins would need
changes, or some control is already doing things in a certain way,
or things being out of scope (out of scope for implementation is
fine, but we need to plan ahead so it is not out of scope for the
design).<br>
</p>
<p>IMHO API design comes first, and it needs to think quite far
ahead, and needs to be incredibly conservative in what it exposes.
Extracting the API from existing code that does not have a fully
fleshed out design, and has a lot of open questions is just not
going to be a good basis for a public API.</p>
<span style="font-size:11.0pt;font-family:"Iosevka Fixed
SS16""><o:p> </o:p></span>
<blockquote type="cite"
cite="mid:DM5PR1001MB21727E4E85D417CE348AF751E5D7A@DM5PR1001MB2172.namprd10.prod.outlook.com">
<div class="WordSection1">
<p style="margin-left:.5in"><span
style="font-family:"Iosevka Fixed SS16""></span>-
The mutable maps, immutability would allow making these
static, saving many objects; when I have some time I can take
a look at how many are in memory when a decent sized FX
application is running; as even Labels are Controls, and
Labels are the base class for any Cell, this number might be
larger than expected and potentially could allow for some
significant memory savings; making it public as-is closes that
road down forever. Immutability does not mean things can't be
changed, it just requires a slightly different mindset (ie.
you combine a standard InputMap with a custom InputMap to form
a new InputMap in which a binding is
changed/overriden/disabled); this was also proposed on
JDK-8091189<o:p></o:p></p>
<p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed
SS16"">Saving memory is a noble goal. You still need
per-instance InputMap though as we need per-instance key
mappings.<o:p></o:p></span></p>
<p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed
SS16"">I think delegating the default mappings to a
separate static input map is still possible, but it will
require essentially a more extensive re-write of skins and
therefore is definitely out of scope.</span></p>
</div>
</blockquote>
<br>
<blockquote type="cite"
cite="mid:DM5PR1001MB21727E4E85D417CE348AF751E5D7A@DM5PR1001MB2172.namprd10.prod.outlook.com">
<div class="WordSection1">
<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" style="margin-left:.5in">- The Control back
reference; I firmly believe this is unnecessary, and also very
undesirable. <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"">It is mostly for convenience of adding key
bindings directly to the input map with
registerKey(KeyBinding, FunctionTag). Other methods also
use it, I suppose we can get the pointer from behavior, but
adding the pointer to registerKey raises the issue of what
if it’s the wrong control, i.e.
control1.getInputMap().registerKey(control2, ...) ?</span></p>
</div>
</blockquote>
<span style="font-size:11.0pt;font-family:"Iosevka Fixed
SS16""><o:p> </o:p></span>
<blockquote type="cite"
cite="mid:DM5PR1001MB21727E4E85D417CE348AF751E5D7A@DM5PR1001MB2172.namprd10.prod.outlook.com">
<div class="WordSection1">
<p class="MsoNormal" style="margin-left:.5in">- Not designing
this using interfaces<o:p></o:p></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 just don’t think there is a value in adding an
interface, but one can be introduced easily.</span></p>
</div>
</blockquote>
<span style="font-size:11.0pt;font-family:"Iosevka Fixed
SS16""><o:p> </o:p></span>
<blockquote type="cite"
cite="mid:DM5PR1001MB21727E4E85D417CE348AF751E5D7A@DM5PR1001MB2172.namprd10.prod.outlook.com">
<div class="WordSection1">
<p class="MsoNormal" style="margin-left:.5in"><span
style="font-size:12.0pt;color:#212121">- The public
BehaviorBase and the new public behaviors for many controls;</span><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"">Two different issues, let’s not bunch them
together. BehaviorBase (or an interface with default
methods) is an important addition and a pre-requisite for
effective use of the new input map (it’s already being used
and is a blocker for RichTextArea, and I have one more
control that needs it).</span></p>
</div>
</blockquote>
<blockquote type="cite"
cite="mid:DM5PR1001MB21727E4E85D417CE348AF751E5D7A@DM5PR1001MB2172.namprd10.prod.outlook.com">
<div class="WordSection1">
<p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed
SS16""><o:p><br>
</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"">Public concrete behaviors are out of scope at
this time.</span></p>
</div>
</blockquote>
<blockquote type="cite"
cite="mid:DM5PR1001MB21727E4E85D417CE348AF751E5D7A@DM5PR1001MB2172.namprd10.prod.outlook.com">
<div class="WordSection1">
<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>
<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 is much more difficult for me to respond to
the second half of your message. I do agree with many
things you’ve said, but all that sounds like a major
re-design and a re-write to me (I could be wrong). One
implicit goal was to retain backward compatibility, and from
that point of view any major changes are simply unlikely. <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"">The requirement of backward compatibility (and
minimization of changes) is is also why I did not introduced
a parallel method of adding user event handlers. I suppose
we
<u>could</u> add this ability to the InputMap, similarly to
the way a user-created key binding takes precedence over a
behavior-created one. This way we can guarantee that
user-specified handlers are always invoked before
behavior-created ones. This can be bolted on the input map
as a separate enhancement, I 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"">Let’s discuss the alternative proposal of
behaviors as translating layers in a separate thread (thank
you for changing the subject and creating a separate
thread!). I feel it’s a more expensive variation of this
design, but I could be wrong.<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"">Thanks again for a very interesting and
stimulating discussion! I sincerely hope we can get to an
agreement soon and move forward.<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>
<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>
<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 <a class="moz-txt-link-rfc2396E" href="mailto:john.hendrikx@gmail.com"><john.hendrikx@gmail.com></a><br>
<b>Date: </b>Saturday, October 14, 2023 at 10:20<br>
<b>To: </b>Andy Goryachev
<a class="moz-txt-link-rfc2396E" href="mailto:andy.goryachev@oracle.com"><andy.goryachev@oracle.com></a>,
<a class="moz-txt-link-abbreviated" href="mailto:openjfx-dev@openjdk.org">openjfx-dev@openjdk.org</a>
<a class="moz-txt-link-rfc2396E" href="mailto:openjfx-dev@openjdk.org"><openjfx-dev@openjdk.org></a><br>
<b>Subject: </b>Re: [External] : Re: [Request for
Comments] Behavior / InputMap<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">On
12/10/2023 21:56, 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 "">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.</span><o:p></o:p></p>
</blockquote>
<p>On simple Controls yes, filters can be used there for
this purpose, even though that's not their purpose. It
works because a Control (usually) is a leaf node. It
breaks down however when you want to change behavior of
the View controls which have deeper control layers. You
may want to override something defined for ListView, but
only if say a focused editable control isn't consuming
that event for a different purpose. A filter won't be
able to do this.<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 "">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.</span><o:p></o:p></p>
</blockquote>
<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 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.</span><o:p></o:p></p>
</blockquote>
<p>I see BehaviorBase moving to a public package though, and
it is not package private, is that intended then?<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" style="margin-bottom:12.0pt"><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?</span><o:p></o:p></p>
</blockquote>
<p>Alright; these things take a lot of time, but I've taken
a few hours to think about it today. First, a lot of
things just triggered me with the current proposal;<o:p></o:p></p>
<p>- The mutable maps, immutability would allow making these
static, saving many objects; when I have some time I can
take a look at how many are in memory when a decent sized
FX application is running; as even Labels are Controls,
and Labels are the base class for any Cell, this number
might be larger than expected and potentially could allow
for some significant memory savings; making it public
as-is closes that road down forever. Immutability does
not mean things can't be changed, it just requires a
slightly different mindset (ie. you combine a standard
InputMap with a custom InputMap to form a new InputMap in
which a binding is changed/overriden/disabled); this was
also proposed on JDK-8091189<o:p></o:p></p>
<p>- The Control back reference; I firmly believe this is
unnecessary, and also very undesirable. Events already
contain this reference, its superflous and requires a new
instance for an (otherwise) similar instance; This is even
done already in places, exactly to avoid having to create
more instances (see #getNode in FocusTraversalInputMap for
example, effectively allowing that class to be static
while providing the focus traversal behavior). This was
also raised on JDK-8091189<o:p></o:p></p>
<p>- Not designing this using interfaces (also raised on
JDK-8091189). With the addition of default methods, we
should favor composable designs instead of being forced to
inherit from a base class in order to provide a custom
implementation. Sure, you can still provide a default
implementation, but public methods should be referring to
the interface so it can be a completely different
implementation. Interfaces prevent using package private
shortcuts where privileged classes can provide a
functionality that users cannot.<o:p></o:p></p>
<p>- The public BehaviorBase and the new public behaviors
for many controls; I'm not convinced behaviors (if we
can't define exactly what their purpose is supposed to be
vs the Control and Skin) are ready to become more than
just an implementation detail.<o:p></o:p></p>
<p>As for high level design, it of course depends on what
the goal here is. The issues linked in the proposal all
call out for a public behavior API, but your proposal
narrows the scope rightfully down to influencing default
reactions to (key?) events only. Making behaviors public
as they are now, and without a clear definition of what
they are, seems definitely premature. I think they first
need to be re-evaluated to see if they are still a good
design at all (after all they're 10+ years old), then
rewritten internally (if the ideas behind them changed),
and only then made public.<o:p></o:p></p>
<p>In your proposal I think the Summary and Motivation are
quite good at outlining a problem to be solved. I'd like
to rephrase that as a goal: "To allow developers to remap,
override or disable the standard behavior of JavaFX
controls (note: behavior here is used in the general
sense)". I think there is no need to mention InputMap,
Behaviors or key bindings here, those are merely possible
means to achieve the goal.<o:p></o:p></p>
<p>I'd then first take a look how this could be achieved
with current JavaFX, and where users are running into a
wall.<o:p></o:p></p>
<p>Most obviously, the way to make controls do something you
want is by using event handlers. Even Behaviors use these
internally, in which we'll later see lies a bit of the
problem.<br>
<br>
# Expectations<o:p></o:p></p>
<p>Just like when a developer sets a Control property
directly to a specific value, when the developers adds an
event handler or listener, he/she can rightfully expect
that FX respects this and does not get in the way. For
the property case, CSS will not override such a property,
for listeners, all listeners receive any callbacks, and
for events, the user registered handlers should take
priority over internal handlers (unlike listeners, event
handlers can consume and act upon events before they reach
the user handler, hence order plays an important role
here).<o:p></o:p></p>
<p>CSS, Skins and Behaviors sharing the same properties,
listeners and event handlers with application developers
has always been a bit of a balancing act; CSS has an
elaborate system to respect user property changes, and
keeps track of these; Skins for the most part manage to
stay out of the application developer's way, mostly
because they primarily use listeners which inherently
don't block listeners added by the application developer.
They also rarely override properties outright that are
also modifiable by the developer.<o:p></o:p></p>
<p>With Behaviors the situation is very different. Event
handlers added by behaviors will consume events,
effectively acting upon them before the application
developer can (you may still see such events as
"consumed", but they will not bubble up further). On top
of that is the fact that EventHandlers are far more
complicated than plain listeners or properties. For
example, a KeyEvent.KEY_PRESSED handler is called before a
KeyEvent.KEY_ANY handler; attempting to override behavior
in a KeyEvent.KEY_ANY handler is therefore impossible when
the behavior to override is using a more specific event
type. Consumption of an event only blocks
capturing/bubbling of the event; other event handlers at
the same level do still see such events, but they're
marked "consumed"; most event handlers should therefore
probably start with a `if (e.isConsumed()) return` line,
but often don't (users often don't do this because they
expect their handlers to be the only ones present, or to
be called first, even though for Controls with Behaviors
this is not actually true).<o:p></o:p></p>
<p># Problems<o:p></o:p></p>
<p>Some of the problems you can expect to see when you want
to act upon an event that has a "default" behavior (versus
ones that don't):<o:p></o:p></p>
<p>- Adding a more generic event handler than the one used
internally will result in the events you are interested in
being consumed already<br>
- Adding the exact same event handler as one used
internally AFTER the control was shown (or re-adding it in
response to something) will result in events you are
interested in being consumed already, or more generally,
an event handler works differently whether they were added
before or after the control was shown...<br>
- Events for which there exist a default behavior are in
some cases consumed even if the behavior could not be
performed (navigation)<br>
<br>
In all the above cases, for events WITHOUT default
behavior, such a user installed handler works exactly as
expected. IMHO there really should be no difference for
the user whether there is a default behavior or not.<o:p></o:p></p>
<p># Causes<o:p></o:p></p>
<p>Almost all of these problems are caused by the fact that
JavaFX's internal handlers share the same lists/mechanisms
as application developers to react to events; these
internal handlers are mixed up with event handlers from
application developers; often the internal ones run first,
but it is very unpredictable:<o:p></o:p></p>
<p>- Is your event handler more generic than an internal
handler? You always run last<br>
- Is your event handler more specific than an internal
handler? You always run first<br>
- Is your event handler the exact same event type as an
internal handler... then:<br>
- Did you add handlers before the control was shown /
skin was created? Yours run first (subject to change no
doubt, we don't guarantee this)<br>
- Did you add handlers after the control was shown?
Yours run last (no guarantees)<br>
- Did you add handlers after the control was shown, but
then its skin was replaced? Your event handlers that used
to run last now run first... (undocumented)<br>
<br>
An innocent change like listening for KeyEvent.ANY vs
KeyEvent.KEY_PRESSED can have big repercussions.<o:p></o:p></p>
<p># How to reach the goal?<o:p></o:p></p>
<p>There are many ways to reach the above stated goal.
Opening up some internal structures that are used by the
internal event handlers is one way, but it effectively
creates a 2nd mechanism to do the same thing. I can
change the internal event handler's internal structures to
do X, or I can create an event handler that does X. For
some of these, both options work, and for others, only
this new mechanism works. Not only is this mostly
compensating for a flaw in the event handling system, but
it also means that you need to be aware of which events
need special treatment. It's even possible that some
events require no special treatment now, but may in the
future, or may need it if the platform changes certain
defaults. In other words, this new mechanism would
effectively need to be used in all cases or you risk your
solution (using standard event handlers) breaking in the
future (or JavaFX would have to freeze input maps and
never change them again -- that's already sort of the
case, but it is good to be aware of that).<o:p></o:p></p>
<p># Alternative solution<o:p></o:p></p>
<p>I would look into seeing if the flaws in the event
handling system can be resolved, so that this mechanism
that is already available, and that users already know
becomes powerful enough to cater to the stated goal. Note
that this doesn't preclude opening up behaviors later, but
it does take away one of the fundamental reasons to do so,
perhaps allowing for quite a different way of exposing
these to users as the primary driver need no longer be
focused on remapping bindings. Perhaps the primary driver
can then be how to design behaviors in such a way that
they can be re-used and easily subclassed; perhaps
behaviors are no longer needed at all, and they can remain
an internal implementation detail, or perhaps they can be
part of skins or controls.<o:p></o:p></p>
<p>I see a few problems that should be addressed if we want
to be able to reach the goal with better event handlers:<o:p></o:p></p>
<p>1) Internal event handlers should NOT use the same
mechanism as user event handlers; effectively, user event
handlers (of any event type, even more general ones) run
first, as if no internal event handlers existed at all.
This is already the case depending on the timing of when
the user added the handlers; the timing is unpredictable
(as stated above) and so I think we have enough leeway to
change this, and enough reason to tighten up the
specification here.<o:p></o:p></p>
<p>2) All internal event handlers run AFTER user ones (per
EventTarget), regardless of when they were added. A
separate list can be used, or the event type system could
support this with some kind of internal flag.<o:p></o:p></p>
<p>3) Internal event handlers can be skipped completely if
the user marks an event as such. This is different from
consuming the event; effectively, the event is not
consumed (and can bubble up to other event targets) but
internal event handlers are not allowed to act upon it.<o:p></o:p></p>
<p>4) All actions triggered by behaviors should be available
as public methods (nested or direct) on their respective
controls, allowing the user to call these as well.<o:p></o:p></p>
<p>The above changes should be enough to support the stated
goal: "To allow developers to remap, override or disable
the standard behavior of JavaFX controls (note: behavior
here is used in the general sense)"<o:p></o:p></p>
<p>To override a standard behavior: install event handler
(which will run first), react to an event, call a public
method triggering the DIFFERENT behavior, consume the
event<br>
To disable a standard behavior: install event handler,
react to an event, mark it as "not for internal use",
effectively disallowing the internal handlers from acting
on it<br>
To remap a standard behavior: combine the above two
solutions<o:p></o:p></p>
<p># New API needed<o:p></o:p></p>
<p>A flag on `Event` that can be set/cleared whenever the
user wants. The flag effectively communicates that the
given event is not to be processed by the "hidden"
internal event handlers added by JavaFX. It could be
called "noDefault" or "skipDefaultBehavior".<o:p></o:p></p>
<p>Depending on the internal changes needed to separate user
event handlers from internal ones, EventType may also need
a small change. For example, if the separation is
implemented by introducing more event types, a convenient
`EventType#toInternal` method could be added to convert a
regular event type to an internal one that is always
processed after standard ones. It's possible such a
method does not need to be public (but could be if users
desire the old unpredictable behavior of mixing user and
internal event handlers).<o:p></o:p></p>
<p># Alternative alternative solution<o:p></o:p></p>
<p>Part of the problem can also be solved by disallowing
internal handlers to listen on the most specific EventType
(ie, don't listen to KeyEvent.KEY_PRESSED, but instead
listen to KeyEvent.ANY). This way a user can be the first
to handle the event in all cases by using a more specific
type (KeyEvent.KEY_PRESSED) or the last in all cases by
using a less specific type (InputEvent.ANY). This leaves
much to be desired, and doesn't solve all of the above
outlined problems, but I mention it to show that there is
quite a lot possible here already by tweaking the event
handling system.<o:p></o:p></p>
<p>--John<o:p></o:p></p>
<p><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 "">Thank you</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">John
Hendrikx <a
href="mailto:john.hendrikx@gmail.com"
moz-do-not-send="true">
<john.hendrikx@gmail.com></a><br>
<b>Date: </b>Thursday, October 12, 2023 at
01:33<br>
<b>To: </b>Andy Goryachev <a
href="mailto:andy.goryachev@oracle.com"
moz-do-not-send="true"><andy.goryachev@oracle.com></a>,
<a href="mailto:openjfx-dev@openjdk.org"
moz-do-not-send="true"
class="moz-txt-link-freetext">openjfx-dev@openjdk.org</a>
<a href="mailto:openjfx-dev@openjdk.org"
moz-do-not-send="true">
<openjfx-dev@openjdk.org></a><br>
<b>Subject: </b>[External] : Re: [Request for
Comments] Behavior / InputMap</span><o:p></o:p></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:</span><o:p></o:p></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"><br>
<span style="font-size:11.0pt"><br>
<br>
</span><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 "">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"
moz-do-not-send="true"
class="moz-txt-link-freetext">
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"
moz-do-not-send="true">
<openjfx-dev-retn@openjdk.org></a>
on behalf of John Hendrikx <a
href="mailto:john.hendrikx@gmail.com"
moz-do-not-send="true">
<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"
moz-do-not-send="true"
class="moz-txt-link-freetext">openjfx-dev@openjdk.org</a>
<a href="mailto:openjfx-dev@openjdk.org"
moz-do-not-send="true">
<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"
moz-do-not-send="true">
<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"
moz-do-not-send="true"><michaelstrau2@gmail.com></a><br>
<b>Cc: </b><a
href="mailto:openjfx-dev@openjdk.org"
moz-do-not-send="true"
class="moz-txt-link-freetext">openjfx-dev@openjdk.org</a>
<a
href="mailto:openjfx-dev@openjdk.org"
moz-do-not-send="true">
<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
style="width:8.052in;height:6.8333in"
id="Picture_x0020_2"
src="cid:part1.Red2Hqmj.6LY70vxB@gmail.com"
class="" width="773" height="656"
border="0"><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"
moz-do-not-send="true">
<openjfx-dev-retn@openjdk.org></a> on behalf of Michael Strauß <a
href="mailto:michaelstrau2@gmail.com" moz-do-not-send="true">
<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"
moz-do-not-send="true"
class="moz-txt-link-freetext">openjfx-dev@openjdk.org</a>
<a
href="mailto:openjfx-dev@openjdk.org"
moz-do-not-send="true">
<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>
</blockquote>
</div>
</div>
</div>
</blockquote>
</body>
</html>