<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
> If we want InputMaps</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
I think InputMap provides substantial value.  I also agree about addressing the Skin/Behavior split.  In fact, I see InputMap as an entity that ties the three parts together:</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
- Control provides a façade</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
- Skin provides the visual representation</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
- Behavior encapsulates event handlers</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
- InputMap maintains the pointers to the event handlers and resolves the priority issues between application and skin event handlers.</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
I've been trying to advance an InputMap implementation [0], which I think helps application, skin, and custom component developers alike, while also solving the priority issue and opening up the behavior customization a bit.</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
There are two POC - one is being incubated as a part of the rich text area in <b>
incubator.input</b> module, the other is a partial implementation using a subset of somewhat complicated controls [1].</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
We went through a series of prolonged discussions.  Among the sticky points were:</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
- desire to have static behaviors, for the purpose of allowing the application to customize the behavior or all the controls of the given type I guess</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
- general dislike of having behavior classes inherit from a BaseBehavior convenience class</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
I am sure there were more, so I think we should continue.  I would like to see InputMap public API because it adds tremendous value without much cost.</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
What do you think?</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
-andy</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
References</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
[0] <a href="https://github.com/andy-goryachev-oracle/Test/blob/main/doc/InputMap/InputMapV3.md" data-outlook-id="5bed0123-c3f5-4a7e-a655-6d191728baa1">
https://github.com/andy-goryachev-oracle/Test/blob/main/doc/InputMap/InputMapV3.md</a></div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
[1] <a href="https://github.com/openjdk/jfx/pull/1495" data-outlook-id="c7eb61b2-fb84-44d8-8026-eb645bece969">
https://github.com/openjdk/jfx/pull/1495</a></div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div id="mail-editor-reference-message-container">
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr;">
</div>
<div class="ms-outlook-mobile-reference-message skipProofing" style="text-align: left; padding: 3pt 0in 0in; border-width: 1pt medium medium; border-style: solid none none; border-color: rgb(181, 196, 223) currentcolor currentcolor; font-family: Aptos; font-size: 12pt; color: black;">
<b>From: </b>John Hendrikx <john.hendrikx@gmail.com><br>
<b>Date: </b>Tuesday, January 13, 2026 at 13:44<br>
<b>To: </b>Andy Goryachev <andy.goryachev@oracle.com>, Martin Fox <martinfox656@gmail.com><br>
<b>Cc: </b>OpenJFX <openjfx-dev@openjdk.org><br>
<b>Subject: </b>Re: [External] : Re: Default event handlers<br>
<br>
</div>
<p class="ms-outlook-mobile-reference-message skipProofing">Hi,</p>
<p class="ms-outlook-mobile-reference-message skipProofing">The InputMap is a user of the event system.  It is basically a configurable event handler for a limited number of event types.  You could write one right now, expose it, and configure mappings, and
 in fact, to save on event handlers, this is exactly how many handlers already work.  Introducing it as an integral part of say Control immediately raises concerns; is InputMap going to be yet another event handler that users will have to fight when they install
 their own?  At most I see this as part of a public Behavior API, where the Behavior can install (default) handlers, that then delegate to an accessible input map for that Behavior.  Swing doesn't have a Control/Behavior/Skin split, but FX does, and I think
 we should remain committed to that instead of making some Swing/QT/Compose Frankenstein hybrid here by copying features without thinking about the bigger picture and how they really fit into FX. </p>
<p class="ms-outlook-mobile-reference-message skipProofing">Furthermore, the current private InputMap implementation is, to put it midly, insanely inefficient, and so I find it incredibly hard to justify using even parts of that design. Everything in it is
 Observable, but nobody will be able to monitor it all for changes as that would entail installing hundreds of handlers for the average TextField input map.  What's also inefficient is that this input map gets recreated for each control, leading to several
 kilobytes of overhead for every TextField in your application. There is just no reason to duplicate input maps like this as they're all going to be same 99.999% of the time. </p>
<p class="ms-outlook-mobile-reference-message skipProofing">If we want InputMaps, then I think we need to solve the Skin/Behavior split first -- this alone will be a huge win for FX, as reskinning then becomes trivial, finally fulfilling the promise that FX
 has made for easily reskinnable controls, as you no longer lose the default platform behavior.  Then with Behaviors also being replaceable, one can much easier allow for custom behaviors that expose fancy things like a fully customizable InputMap (although
 please, let's not make it observable, and let's de-duplicate them).</p>
<p class="ms-outlook-mobile-reference-message skipProofing">--John</p>
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr;">
<br>
</div>
<div class="moz-cite-prefix">On 13/01/2026 18:35, Andy Goryachev wrote:</div>
<blockquote>
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
I agree with Martin that this issue is mostly limited to Controls because of the skins.  What was the main objection to the InputMap idea I proposed?</div>
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
I do want to ask Martin one thing though: what do you mean by "The only obvious gap in the public API is that there’s no way for a handler or filter to communicate with the dispatcher that invoked it."  Can you give an example?</div>
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
Thanks!</div>
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
-andy</div>
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div id="mail-editor-reference-message-container">
<div class="ms-outlook-mobile-reference-message skipProofing" style="text-align: left; padding: 3pt 0in 0in; border-width: 1pt medium medium; border-style: solid none none; border-color: rgb(181, 196, 223) currentcolor currentcolor; font-family: Aptos; font-size: 12pt; color: black;">
<b>From: </b>openjfx-dev <a href="mailto:openjfx-dev-retn@openjdk.org" class="moz-txt-link-rfc2396E" data-outlook-id="23c82205-eb4c-455a-a3cb-acf3d2ad44fc">
<openjfx-dev-retn@openjdk.org></a> on behalf of Martin Fox <a href="mailto:martinfox656@gmail.com" class="moz-txt-link-rfc2396E" data-outlook-id="99dd0295-d040-4309-a724-9d48393fa179">
<martinfox656@gmail.com></a><br>
<b>Date: </b>Tuesday, January 13, 2026 at 09:00<br>
<b>To: </b>John Hendrikx <a href="mailto:john.hendrikx@gmail.com" class="moz-txt-link-rfc2396E" data-outlook-id="b4f24e17-6733-475f-91db-7b37504af0df">
<john.hendrikx@gmail.com></a><br>
<b>Cc: </b>OpenJFX <a href="mailto:openjfx-dev@openjdk.org" class="moz-txt-link-rfc2396E" data-outlook-id="a702ec4e-be62-4aab-8b7e-7cdd9c30783e">
<openjfx-dev@openjdk.org></a><br>
<b>Subject: </b>Re: [External] : Re: Default event handlers<br>
<br>
</div>
<div class="ms-outlook-mobile-reference-message skipProofing">I didn’t intend to re-open all of these debates. I just wanted to point out that JavaFX in general uses dispatchers to process events so there’s no existing concept of default handlers outside of
 Control. If Control had implemented InputMap using a dispatcher we probably wouldn’t be having this conversation.</div>
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr;">
<br>
</div>
<div class="ms-outlook-mobile-reference-message skipProofing">I still believe this is a local problem for Control and it can craft its own solution. It doesn’t even have to involve handlers; look at how Scene and Menu handle accelerators. Whatever Control wants
 to do almost all of the tools are there. The only obvious gap in the public API is that there’s no way for a handler or filter to communicate with the dispatcher that invoked it. Rather than add a specialized bit like this PR does I thought it might be worth
 considering a more generalized solution (I can think of a few) but I’m actually fine with preventDefault() since it’s based on an existing standard.</div>
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr;">
<br>
</div>
<div class="ms-outlook-mobile-reference-message skipProofing">Martin</div>
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr;">
<br>
</div>
<blockquote>
<div class="ms-outlook-mobile-reference-message skipProofing">On Jan 13, 2026, at 4:52 AM, John Hendrikx
<a href="mailto:john.hendrikx@gmail.com" class="moz-txt-link-rfc2396E" data-outlook-id="f4784fe3-8a51-4d82-b08e-aec962cf1853">
<john.hendrikx@gmail.com></a> wrote:</div>
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr;">
<br>
</div>
<p class="ms-outlook-mobile-reference-message skipProofing"><br>
</p>
<div class="moz-cite-prefix">On 13/01/2026 00:43, Andy Goryachev wrote:</div>
<blockquote>
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt;">
<br>
</div>
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt;">
The reason I mentioned #2 is that it is somewhat relevant to the discussion, as in "why do we need to write custom dispatchers at all?"  There should be only two methods, in my opinion, one that dispatches an event that bubbles up (with filters and handlers),
 and one that sends an event to a single target Node and nothing else.  <rant>Somehow, Swing got the Events right - it manages to dispatch one (1) event in total, and the dispatching stops once the event is consumed.  The FX decided it needed to reinvent the
 wheel and leave multiple booby traps in the process.</rant></div>
</blockquote>
<p class="ms-outlook-mobile-reference-message skipProofing">Although I agree that how FX solved events is sub-optimal, there is a real need here to communicate to the EventHandler on which object it resides.  EventHandler instances are expensive when you need
 to attach one to every Cell in a TableView, and so to re-use a single instance, you need to know which Cell the event applies to.  The source field (which is supposed to be constant) has been abused for this, making events non-constant requiring cloning before
 they can be dispatched to their final target.  This cloning then caused the "isConsumed" problem.  Perhaps we should just make the source field mutable as well, so the cloning isn't needed.</p>
<p class="ms-outlook-mobile-reference-message skipProofing">The solution to this problem at the time should not have been to modify events, but to have made event handlers be BiConsumers, with the Event **and** Node being passed to the callback (and a "convenience"
 method that delegates to the BiConsumer variant that accepts only Consumer<Event> -- we may be able to still do this...)</p>
<blockquote>
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt;">
<br>
</div>
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr; font-family: "Iosevka Fixed SS16", Arial, Helvetica, sans-serif; font-size: 12pt;">
This isn't exactly rocket science, we should be able to figure something out.  Maybe there is another option that will satisfy everyone?</div>
</blockquote>
<p class="ms-outlook-mobile-reference-message skipProofing">I think the issue isn't so much in event dispatching, but in the Skin/Behavior system itself.  Skin/Behaviors in FX is like giving root access to every user on your system.  Sure it is convenient that
 everyone can do whatever they want, and as long as everyone behaves, everything works great.  However one malicious user can interfere with others or leave behind hooks that later come to bite you.</p>
<p class="ms-outlook-mobile-reference-message skipProofing">Controls are HOSTS for Skins and Behaviors.  Skins and Behaviors are clients.  They should be restricted to a very specific subset of functionality that benefits the host and is predictable for the
 host:</p>
<p class="ms-outlook-mobile-reference-message skipProofing">- Skins get ownership of the children list of the Control; while a Skin is installed, the host should not be allowed to make modifications<br>
- Skins can monitor properties for changes but this should never lead to a direct observable change on the main control that a subsequent installed listener may observe; in other words, listener order should be irrelevant for what the Skin does in order to
 share the listener infrastructure without interference.  Skins are free to directly take action on the children (which they own exclusively), just not on the main control; such actions should instead be deferred, usually by requesting a layout (this is usually
 already the case, but it is good to make this explicit so we can decide what a Skin is doing is a bug or not).<br>
- Behaviors can react to events at the lowest precedence, and exclusively only take action when receiving an event; this means that blocking all events will automatically mean the Behavior no longer does anything, but also that selectively blocking events allows
 some control over Behaviors<br>
- Behaviors can co-modify properties on the Control, but this should be clearly documented; controls are free to restrict this set (ie. a Behavior has no business modifying the "wrapText" property, or things like layout properties -- most often they do their
 work through pseudo class changes and modifying the value a control represents).</p>
<p class="ms-outlook-mobile-reference-message skipProofing">That should really be all that is needed for a functioning Skin/Behavior system; no need for root access.</p>
<p class="ms-outlook-mobile-reference-message skipProofing">Of course, root access to the Control is a ship that has sailed a long time ago; but that doesn't mean we can't introduce a client API for Skins/Behaviors.  All that really takes is passing an object
 to the Skin/Behavior when it is installed. This object is an interface with which the Skin/Behavior can do their work. Should they choose to not circumvent this API, and do all their work through this API, they can remove all their clean-up code, as the Control
 can now do this automatically.  This will greatly simplify skins, and remove a whole avenue of potential bugs.</p>
<p class="ms-outlook-mobile-reference-message skipProofing">All work done through this API can be monitored by the Control. The control can:<br>
- Track what is installed (for later clean-up)<br>
- Reject installation of listeners/handlers it doesn't want to expose<br>
- Ensure that event handlers are installed at lowest precedence.  This can be kept internal, so many solutions are possible: separate lists, default event handlers (internal API), priorities, etc.</p>
<p class="ms-outlook-mobile-reference-message skipProofing">Everything you'd expect a host Control to be able to do, including forcefully removing all traces of a previously installed Skin, and disallowing it further access should it attempt to use the API
 again after a new Skin is installed. That's however not a requirement; all we'd need is that interface, and encourage Skins/Behaviors to use it.  Correctly behaved Skins/Behaviors then get all the benefits, and will stop interfering with user code.  This means
 of course modifications to existing skins, but it is mostly in their registration logic (which I think we modified like 5 times already).</p>
<p class="ms-outlook-mobile-reference-message skipProofing">The minimum API needed can be fairly small, and does not need to include accessors for every property and handler with some smart signatures.  For example:</p>
<p class="ms-outlook-mobile-reference-message skipProofing">    <span style="font-family: Consolas; font-size: 11pt; background-color: rgb(255, 255, 255);">
<T, P </span><span style="font-family: Consolas; font-size: 11pt; color: rgb(0, 0, 160); background-color: rgb(255, 255, 255);"><b>extends</b></span><span style="font-family: Consolas; font-size: 11pt; background-color: rgb(255, 255, 255);"> ReadOnlyProperty<T>>
</span><span style="font-family: Consolas; font-size: 11pt; color: rgb(0, 0, 160); background-color: rgb(255, 255, 255);"><b>void</b></span><span style="font-family: Consolas; font-size: 11pt; background-color: rgb(255, 255, 255);"> addListener(Function<C,
 P> supplier, Consumer<T> subscriber)</span></p>
<p class="ms-outlook-mobile-reference-message skipProofing">Allows installation of a listener by doing:</p>
<p class="ms-outlook-mobile-reference-message skipProofing">    <span style="font-family: Consolas; font-size: 11pt; background-color: rgb(255, 255, 255);">
api.addListener(Slider::minProperty, v -> { ... });</span><br>
<br>
In this way we can isolate and track what Skins/Behaviors are doing, ensure they don't interfere with user operations on the Control and also ensure guaranteed clean-up (if they refrain from accessing the Control directly).</p>
<p class="ms-outlook-mobile-reference-message skipProofing">--John</p>
<p class="ms-outlook-mobile-reference-message skipProofing"><br>
</p>
</blockquote>
<div class="ms-outlook-mobile-reference-message skipProofing" style="direction: ltr;">
<br>
</div>
</div>
</blockquote>
</div>
</body>
</html>