<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
Replying here, for some reason I did not receive your original
message Martin.
<p>In reply to Martin's comments:<br>
</p>
<p>Thanks for looking into the event handling system already; I'm
certain there are some solutions here that can keep internals and
user event handlers seperated, and you found a few alternatives
that I overlooked (I admittedly did not look that deep, just
assumed it would be possible or could be changed to make it
possible).</p>
<p>I'm not sure about making EventHandlerManager public, although
that could certainly help to address the problem; I think the API
we have (addEventHandler/removeEventHandler) ought to be
sufficient for users to manage their handlers; it's just that FX
handlers need to be called last so the user has a decent change of
overriding behavior.</p>
<p>As event handlers can get added/removed at any time by changing
the Skin or Behavior, even then the order of whether internal FX
handlers run first or last should not change (and I think we
shouldn't burden the user with having to manage the order if it
changes).</p>
<p>
<blockquote type="cite"><span style="font-size:11.0pt">Internally
the first problem also has a solution. EventDispatchers which
manage event handlers and filters are called
EventHandlerManagers (the bucket I referred to earlier is the
Node’s event handler manager). Again, a Node can have multiple
dispatchers and any of them could be an EventHandlerManager.
For example, the Control class could have an internal
EventHandlerManager with its own collection of handlers and
filters that is entirely separate from the Node’s. It would be
up to the class to determine whether its manager executed
before or after the Node’s.</span></blockquote>
</p>
<p>I also like that; only Control's would need it, so it wouldn't be
a burden for all Nodes.</p>
<p>--<br>
</p>
<p>In reply to Andy's question:<br>
</p>
<p>The problem we're trying to address is that user event handlers
are currently somewhat unpredictable as to when they get executed;
if added before the Skin is installed, they will be first and will
be more powerful as they can consume events before the behavior
handlers can get to them. If installed after the skin (or if
they're ever need to be refreshed by adding/removing them during
operation of your control) then they will end up AFTER the skin
event handlers and things that worked before now don't anymore.</p>
<p>On top of that, even if you do install your event handler first,
but it is of a more general type (ie. KeyEvent.ANY vs
KeyEvent.KEY_PRESSED), then the PRESSED handler gets executed
first regardless; the ANY handler will only receive a consumed
event... What we're saying is that user handlers should be
considered more important than the default FX internal behaviorial
handlers; those should be triggered if no user handler is
interested in the event.</p>
<p>The problems that this addresses are:</p>
<p>- It will be possible to do a lot of the things that people would
like to change the Behavior for<br>
- Event handler order will no longer depend on circumstances like
when was the Skin/Behavior installed or changed; having a
predictable and explainable system is very important</p>
<p>As I said before, the fact that the Skins/Behaviors are mixing
their concerns directly with user concerns (by manipulating the
same Control the user is manipulating) is a bit iffy; for
listeners (primarily used by Skins) this is fairly safe as they
always all get called and no "state" changes (although see bugs in
the old value handling for change listeners), but for event
handlers installed by behaviors, once an event is consumed, a user
event handler can't do anything anymore...<br>
</p>
<p>--John<br>
</p>
<p><br>
</p>
<div class="moz-cite-prefix">On 16/10/2023 20:31, Andy Goryachev
wrote:<br>
</div>
<blockquote type="cite"
cite="mid:DM5PR1001MB2172A57738219E3063E67318E5D7A@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)">
<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:Optima-Regular;
panose-1:2 0 5 3 6 0 0 2 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.apple-converted-space
{mso-style-name:apple-converted-space;}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>
<div class="WordSection1">
<p class="MsoNormal"><span
style="font-size:11.0pt;font-family:"Iosevka Fixed
SS16"">Martin:<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 would be the use case for creating a public
EventHandlerManager?<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"">In general, what is the problem we are trying to
address that is impossible to solve using the existing
machinery?<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>
<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">Martin
Fox <a class="moz-txt-link-rfc2396E" href="mailto:martin@martinfox.com"><martin@martinfox.com></a><br>
<b>Date: </b>Saturday, October 14, 2023 at 14:48<br>
<b>To: </b>John Hendrikx
<a class="moz-txt-link-rfc2396E" href="mailto:john.hendrikx@gmail.com"><john.hendrikx@gmail.com></a><br>
<b>Cc: </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>
<p class="MsoNormal"><span style="font-size:11.0pt">I’ve
been digging around in the code to get some context on
the existing machinery for ordering event handler
execution. I haven’t had time to write up test cases so
all of this is based on reading the spec and the code.<o:p></o:p></span></p>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">The
current problem is that all handlers for a given Node
are thrown into the same bucket and that bucket isn't
delivering the execution order clients expect. Within
the existing framework the minimal solution would be
to (a) segregate handlers into separate buckets and
(b) control the order in which the buckets are
processed.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">The
second problem is solved. The order of execution is
controlled by the EventDispatchChain and there are
public API’s for manipulating it. Note that it’s
possible for one Node to have multiple dispatchers in
the chain and anyone can take a fully constructed Node
and add an EventDispatcher to it (if you’re
subclassing a node you would override
buildEventDispatchChain).<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">Internally
the first problem also has a solution.
EventDispatchers which manage event handlers and
filters are called EventHandlerManagers (the bucket I
referred to earlier is the Node’s event handler
manager). Again, a Node can have multiple dispatchers
and any of them could be an EventHandlerManager. For
example, the Control class could have an internal
EventHandlerManager with its own collection of
handlers and filters that is entirely separate from
the Node’s. It would be up to the class to determine
whether its manager executed before or after the
Node’s.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">(In
the public API anyone can implement an EventDispatcher
but if they want to support the existing calls for
managing event handlers and filters they are on their
own. Personally I think we should provide an
EventHandlerManager for public use.)<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">Martin<o:p></o:p></span></p>
</div>
<div>
<div>
<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">
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">On
Oct 14, 2023, at 10:19 AM, John Hendrikx
<a class="moz-txt-link-rfc2396E" href="mailto:john.hendrikx@gmail.com"><john.hendrikx@gmail.com></a> wrote:<o:p></o:p></span></p>
</div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
<div>
<div>
<p class="MsoNormal"><span
style="font-size:10.5pt;font-family:Optima-Regular">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;font-variant-caps:
normal;orphans: auto;text-align:start;widows:
auto;-webkit-text-stroke-width:
0px;word-spacing:0px">
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt">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<span
class="apple-converted-space"> </span><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>
</div>
</blockquote>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt;font-variant-caps:
normal;orphans: auto;text-align:start;widows:
auto;-webkit-text-stroke-width:
0px;word-spacing:0px">
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt">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>
</div>
</blockquote>
<blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt;font-variant-caps:
normal;orphans: auto;text-align:start;widows:
auto;-webkit-text-stroke-width:
0px;word-spacing:0px">
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt">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>
</div>
</blockquote>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">I
see BehaviorBase moving to a public package
though, and it is not package private, is that
intended then?<o:p></o:p></span></p>
<blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt;font-variant-caps:
normal;orphans: auto;text-align:start;widows:
auto;-webkit-text-stroke-width:
0px;word-spacing:0px">
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"
style="margin-bottom:12.0pt"><span
style="font-size:11.0pt">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>
</div>
</blockquote>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">-
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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">-
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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">-
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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">-
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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">#
Problems<o:p></o:p></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">-
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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">#
Causes<o:p></o:p></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">-
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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">#
How to reach the goal?<o:p></o:p></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">#
Alternative solution<o:p></o:p></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">#
New API needed<o:p></o:p></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">#
Alternative alternative solution<o:p></o:p></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular">--John<o:p></o:p></span></p>
<p style="caret-color: rgb(0, 0,
0);font-variant-caps:
normal;text-align:start;-webkit-text-stroke-width:
0px;word-spacing:0px">
<span
style="font-size:10.5pt;font-family:Optima-Regular"><o:p> </o:p></span></p>
<blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt;font-variant-caps:
normal;orphans: auto;text-align:start;widows:
auto;-webkit-text-stroke-width:
0px;word-spacing:0px">
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt">Thank you</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt">-andy</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div id="mail-editor-reference-message-container">
<div>
<div style="border:none;border-top:solid
windowtext 1.0pt;padding:3.0pt 0in 0in
0in;border-color:currentcolor
currentcolor;border-image: none">
<p class="MsoNormal"
style="margin-bottom:12.0pt"><b><span
style="font-size:12.0pt">From:<span
class="apple-converted-space"> </span></span></b><span
style="font-size:12.0pt">John Hendrikx<span
class="apple-converted-space"> </span><a
href="mailto:john.hendrikx@gmail.com"
moz-do-not-send="true"><john.hendrikx@gmail.com></a><br>
<b>Date:<span
class="apple-converted-space"> </span></b>Thursday,
October 12, 2023 at 01:33<br>
<b>To:<span
class="apple-converted-space"> </span></b>Andy
Goryachev<span
class="apple-converted-space"> </span><a
href="mailto:andy.goryachev@oracle.com" moz-do-not-send="true"><andy.goryachev@oracle.com></a>,<span
class="apple-converted-space"> </span><a
href="mailto:openjfx-dev@openjdk.org"
moz-do-not-send="true"
class="moz-txt-link-freetext">openjfx-dev@openjdk.org</a><span
class="apple-converted-space"> </span><a
href="mailto:openjfx-dev@openjdk.org"
moz-do-not-send="true"><openjfx-dev@openjdk.org></a><br>
<b>Subject:<span
class="apple-converted-space"> </span></b>[External]
: Re: [Request for Comments] Behavior /
InputMap</span><o:p></o:p></p>
</div>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular"> <o:p></o:p></span></p>
<div>
<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>
</div>
<blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt">Dear John:</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt">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>
</div>
</blockquote>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"><br>
<br>
<br>
</span><o:p></o:p></p>
</div>
<blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt">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>
</div>
</blockquote>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt">And, if we
look at the three bullet points</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<p style="margin-left:.5in"><span
style="font-size:10.5pt;font-family:Optima-Regular">-
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></span></p>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt">I absolutely
agree, and in fact the first three are
indeed a part of the proposal. Well,
the 3<sup>rd</sup><span
class="apple-converted-space"> </span>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>
</div>
</blockquote>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">I
don't see how your proposal addresses the
first point. <o:p></o:p></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">I've
been reading the comments attached to<span
class="apple-converted-space"> </span><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><span
class="apple-converted-space"> </span>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></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">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. <span
class="apple-converted-space"> </span><o:p></o:p></span></p>
<blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt">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>
</div>
</blockquote>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">--John<o:p></o:p></span></p>
<blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt">-andy</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div
id="mail-editor-reference-message-container">
<div>
<div style="border:none;border-top:solid
windowtext 1.0pt;padding:3.0pt 0in 0in
0in;border-color:currentcolor
currentcolor;border-image: none">
<p class="MsoNormal"
style="margin-bottom:12.0pt"><b><span
style="font-size:12.0pt">From:<span
class="apple-converted-space"> </span></span></b><span
style="font-size:12.0pt">openjfx-dev<span
class="apple-converted-space"> </span><a
href="mailto:openjfx-dev-retn@openjdk.org" moz-do-not-send="true"><openjfx-dev-retn@openjdk.org></a><span
class="apple-converted-space"> </span>on
behalf of John Hendrikx<span
class="apple-converted-space"> </span><a
href="mailto:john.hendrikx@gmail.com" moz-do-not-send="true"><john.hendrikx@gmail.com></a><br>
<b>Date:<span
class="apple-converted-space"> </span></b>Wednesday,
October 11, 2023 at 01:04<br>
<b>To:<span
class="apple-converted-space"> </span></b><a
href="mailto:openjfx-dev@openjdk.org" moz-do-not-send="true"
class="moz-txt-link-freetext">openjfx-dev@openjdk.org</a><span
class="apple-converted-space"> </span><a
href="mailto:openjfx-dev@openjdk.org" moz-do-not-send="true"><openjfx-dev@openjdk.org></a><br>
<b>Subject:<span
class="apple-converted-space"> </span></b>Re:
[Request for Comments] Behavior /
InputMap</span><o:p></o:p></p>
</div>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<div>
<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>
</div>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular"> <span
class="apple-converted-space"> </span>control.addEventHandler(KeyEvent.KEY_PRESSED,
e -> {<br>
<span
class="apple-converted-space"> </span>if
(e.getCode() == KeyCode.LEFT) {<br>
<span
class="apple-converted-space"> </span>e.consume();
// stop default behavior<br>
<span
class="apple-converted-space"> </span>}<br>
<span
class="apple-converted-space"> </span>});<o:p></o:p></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">...
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></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">-
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></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">So
in short, what I think this should
be about is:<o:p></o:p></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">-
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></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">Future:<o:p></o:p></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">-
Make behaviors public and allow
Behaviors to be replaced with
-fx-behavior type CSS syntax /
control.setBehavior calls<o:p></o:p></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">--John<o:p></o:p></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular"> <o:p></o:p></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">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></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">In
fact, thinking about all of this a
bit more,<span
class="apple-converted-space"> </span><o:p></o:p></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular"> <o:p></o:p></span></p>
<p><span
style="font-size:10.5pt;font-family:Optima-Regular">On
10/10/2023 19:54, Andy Goryachev
wrote:<o:p></o:p></span></p>
<blockquote
style="margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt">Re-sending
with a smaller image (256kb
limit, really?).</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div
id="mail-editor-reference-message-container">
<div>
<div
style="border:none;border-top:solid
windowtext 1.0pt;padding:3.0pt
0in 0in
0in;border-color:currentcolor
currentcolor;border-image: none">
<p class="MsoNormal"
style="margin-bottom:12.0pt"><b><span
style="font-size:12.0pt">From:<span
class="apple-converted-space"> </span></span></b><span
style="font-size:12.0pt">Andy
Goryachev<span
class="apple-converted-space"> </span><a
href="mailto:andy.goryachev@oracle.com" moz-do-not-send="true"><andy.goryachev@oracle.com></a><br>
<b>Date:<span
class="apple-converted-space"> </span></b>Tuesday,
October 10, 2023 at 10:49<br>
<b>To:<span
class="apple-converted-space"> </span></b>Michael
Strauß<span
class="apple-converted-space"> </span><a
href="mailto:michaelstrau2@gmail.com" moz-do-not-send="true"><michaelstrau2@gmail.com></a><br>
<b>Cc:<span
class="apple-converted-space"> </span></b><a
href="mailto:openjfx-dev@openjdk.org" moz-do-not-send="true"
class="moz-txt-link-freetext">openjfx-dev@openjdk.org</a><span
class="apple-converted-space"> </span><a
href="mailto:openjfx-dev@openjdk.org"
moz-do-not-send="true"><openjfx-dev@openjdk.org></a><br>
<b>Subject:<span
class="apple-converted-space"> </span></b>Re:
[Request for Comments]
Behavior / InputMap</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt">Dear
Michael:</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt">Here
is a use case for
(re-)mapping by the user at
runtime:</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><image002.jpg><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt">(key
mappings UI in Eclipse).</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt">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>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt">Whether
the InputMap contains the
reference to its control or
not is a minor
implementation detail, I
think.</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt">-andy</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span
style="font-size:11.0pt"> </span><o:p></o:p></p>
</div>
<div
id="mail-editor-reference-message-container">
<div>
<div
style="border:none;border-top:solid
windowtext
1.0pt;padding:3.0pt 0in 0in
0in;border-color:currentcolor currentcolor;border-image: none">
<p class="MsoNormal"
style="margin-bottom:12.0pt"><b><span
style="font-size:12.0pt">From:<span class="apple-converted-space"> </span></span></b><span
style="font-size:12.0pt">openjfx-dev<span
class="apple-converted-space"> </span><a
href="mailto:openjfx-dev-retn@openjdk.org"
moz-do-not-send="true"><openjfx-dev-retn@openjdk.org></a><span
class="apple-converted-space"> </span>on behalf of Michael Strauß<span
class="apple-converted-space"> </span><a
href="mailto:michaelstrau2@gmail.com" moz-do-not-send="true"><michaelstrau2@gmail.com></a><br>
<b>Date:<span
class="apple-converted-space"> </span></b>Tuesday,
October 10, 2023 at
10:36<br>
<b>To:<span
class="apple-converted-space"> </span></b><br>
<b>Cc:<span
class="apple-converted-space"> </span></b><a
href="mailto:openjfx-dev@openjdk.org" moz-do-not-send="true"
class="moz-txt-link-freetext">openjfx-dev@openjdk.org</a><span
class="apple-converted-space"> </span><a
href="mailto:openjfx-dev@openjdk.org"
moz-do-not-send="true"><openjfx-dev@openjdk.org></a><br>
<b>Subject:<span
class="apple-converted-space"> </span></b>Re:
[Request for Comments]
Behavior / InputMap</span><o:p></o:p></p>
</div>
<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>
</div>
</blockquote>
</div>
</div>
</blockquote>
</div>
</div>
</blockquote>
</div>
</blockquote>
</div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
</div>
</div>
</div>
</blockquote>
</body>
</html>