<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <div class="moz-cite-prefix">On 12/10/2023 21:56, Andy Goryachev
      wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:DM5PR1001MB2172AFC250B1590E05D8A794E5D3A@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"">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></p>
      </div>
    </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.<br>
    </p>
    <blockquote type="cite"
cite="mid:DM5PR1001MB2172AFC250B1590E05D8A794E5D3A@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"">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></p>
      </div>
    </blockquote>
    <blockquote type="cite"
cite="mid:DM5PR1001MB2172AFC250B1590E05D8A794E5D3A@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"">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></p>
      </div>
    </blockquote>
    <p>I see BehaviorBase moving to a public package though, and it is
      not package private, is that intended then?<br>
    </p>
    <blockquote type="cite"
cite="mid:DM5PR1001MB2172AFC250B1590E05D8A794E5D3A@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"">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?<br>
            <br>
          </span></p>
      </div>
    </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;</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</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</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.</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.</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.<br>
    </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.</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.</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<br>
    </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).</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.<br>
    </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).<br>
    </p>
    <p># Problems<br>
    </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):</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.</p>
    <p># Causes<br>
    </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:</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.</p>
    <p># How to reach the goal?<br>
    </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).</p>
    <p># Alternative solution</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.</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:</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.</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.</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.</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.<br>
    </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)"</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<br>
    </p>
    <p># New API needed<br>
    </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".</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).</p>
    <p># Alternative alternative solution</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.<br>
    </p>
    <p>--John<br>
    </p>
    <p><br>
    </p>
    <blockquote type="cite"
cite="mid:DM5PR1001MB2172AFC250B1590E05D8A794E5D3A@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"">Thank you<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">-andy<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <div id="mail-editor-reference-message-container">
          <div>
            <div style="border:none;border-top:solid #B5C4DF
              1.0pt;padding:3.0pt 0in 0in 0in">
              <p class="MsoNormal" style="margin-bottom:12.0pt"><b><span
                    style="font-size:12.0pt;color:black">From:
                  </span></b><span style="font-size:12.0pt;color:black">John
                  Hendrikx <a class="moz-txt-link-rfc2396E" href="mailto:john.hendrikx@gmail.com"><john.hendrikx@gmail.com></a><br>
                  <b>Date: </b>Thursday, October 12, 2023 at 01:33<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>[External] : Re: [Request for
                  Comments] Behavior / InputMap<o:p></o:p></span></p>
            </div>
            <p><o:p> </o:p></p>
            <div>
              <p class="MsoNormal"><span style="font-size:11.0pt">On
                  11/10/2023 19:44, Andy Goryachev wrote:<o:p></o:p></span></p>
            </div>
            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 "">Dear John:</span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 ""> </span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 "">Seems like addEventFilter() was
                  specifically designed to intercept events before any
                  other handlers, so I see no problem there.</span><o:p></o:p></p>
            </blockquote>
            <p>This is a misunderstanding of what filters are for. 
              They're called in the capturing phase and they can prevent
              an event from reaching its intended target, but you want
              it to reach the intended target FIRST, as you still want
              to give the target the chance to be the first to act upon
              the event.  For example, let's say I want to attach a
              function to the SPACE key in some specialized HBox, it
              should only do something when something closer to the
              target doesn't need it first (like a nested HBox of the
              same type, or an active TextField that uses SPACE for
              input).  Now if HBox had some FX default event handler
              that consumed SPACE, I have no options to override SPACE
              anymore; the filter is not a good spot, as its too early,
              and the handler is not a good spot because Behavior
              handlers were added before mine was.<o:p></o:p></p>
            <p class="MsoNormal"><span style="font-size:11.0pt"><br>
                <br>
                <o:p></o:p></span></p>
            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 ""> </span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 "">I somewhat disagree about the
                  purpose of the key mapping system – the proposed
                  solution solves two existing issues (the skin/behavior
                  mappings and the user mappings) in one neat package. 
                  Every other instrument such as addEventHandler/Filter
                  is still there.</span><o:p></o:p></p>
            </blockquote>
            <p>I'm saying that the need for this would be almost
              non-existent if user event handlers weren't considered
              less important than FX ones. You have to be careful that
              there aren't two ways of doing things here:<o:p></o:p></p>
            <p>If the event you wish to give an alternative purpose to
              is unused by FX, you can use an event handler; otherwise
              you must disable it (so you can use an event handler!) or
              remap it (using an alternative system).  Note that if FX
              at some point decides to "claim" another mapping, that
              would be a breaking change as some user event handlers may
              cease to function.<o:p></o:p></p>
            <p>This is why I think the input mapping system should stay
              hidden; its an implementation detail of the Event handlers
              added by FX so they don't need to write long
              if/else/switch chains, and so they can more easily switch
              out mappings depending on state.  Opening up the input map
              effectively is being able to influence those FX added
              event handlers to do something different, while there is a
              perfectly good way of doing that already: add your own
              event handler (with higher priority).<o:p></o:p></p>
            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 ""> </span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 "">And, if we look at the three bullet
                  points</span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 ""> </span><o:p></o:p></p>
              <p style="margin-left:.5in">- Ensure user event handlers
                have priority over behavior/inputmap added ones<br>
                - Ensure all behavior actions are available as methods
                on controls<br>
                - Ensure that if a key is handled by the control, that
                it is ONLY consumed when it actually triggers an action
                (navigation keys get consumed regardless, even if no
                focus change results, that's wrong).<o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 "">I absolutely agree, and in fact the
                  first three are indeed a part of the proposal.  Well,
                  the 3<sup>rd</sup> one might unfortunately be a
                  subject of backward compatibility limitation since one
                  of the requirements was no behavior change w.r.t. the
                  earlier versions.  We can always change the behavior
                  if we have a completing reason and go through the
                  usual process, nothing in the proposal precludes that.</span><o:p></o:p></p>
            </blockquote>
            <p>I don't see how your proposal addresses the first point. 
              <o:p></o:p></p>
            <p>I've been reading the comments attached to <a
                href="https://bugs.openjdk.org/browse/JDK-8091189"
                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.Sn2lY0tS.vx5MjAex@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>
      </div>
    </blockquote>
  </body>
</html>