<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>Hi Andy,<br>
    </p>
    <div class="moz-cite-prefix">On 16/10/2023 21:43, Andy Goryachev
      wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:DM5PR1001MB21727E4E85D417CE348AF751E5D7A@DM5PR1001MB2172.namprd10.prod.outlook.com">
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      <meta name="Generator" content="Microsoft Word 15 (filtered
        medium)">
      <!--[if !mso]><style>v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style><![endif]-->
      <style>@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}@font-face
        {font-family:"Yu Gothic";
        panose-1:2 11 4 0 0 0 0 0 0 0;}@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}@font-face
        {font-family:"Iosevka Fixed SS16";
        panose-1:2 0 5 9 3 0 0 0 0 4;}@font-face
        {font-family:"Times New Roman \(Body CS\)";
        panose-1:2 11 6 4 2 2 2 2 2 4;}@font-face
        {font-family:"\@Yu Gothic";
        panose-1:2 11 4 0 0 0 0 0 0 0;}@font-face
        {font-family:"Iosevka Fixed SS16 ";
        panose-1:2 0 5 9 3 0 0 0 0 4;}p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        font-size:10.0pt;
        font-family:"Calibri",sans-serif;}a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}span.EmailStyle20
        {mso-style-type:personal-reply;
        font-family:"Iosevka Fixed SS16";
        color:windowtext;}.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;
        mso-ligatures:none;}div.WordSection1
        {page:WordSection1;}</style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
      <div class="WordSection1">
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">John,<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">I understand this message was sent before the
            one with an alternative proposal, so I’ll address those
            parts that discuss the original input map one.<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Also, I suspect that the major redesign of FX is
            highly unlikely - we simply don’t have the resources to do
            that.<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p style="margin-left:.5in">I see BehaviorBase moving to a
          public package though, and it is not package private, is that
          intended then?<o:p></o:p></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Yes, the BehaviorBase is public for two reasons:<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">1. to be used as a key for behavior-specific
            mappings<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">2. provide the second part of the InputMap APIs
            intended for behaviors<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">It is not the goal to make concrete behaviors
            public at this time.</span></p>
      </div>
    </blockquote>
    <p>My problem here is that by making this class public (which IMHO
      is not a good design) will lock us out of improving this later.  <br>
    </p>
    <p>Nothing Behavior related should be made public without a full
      design of how Behaviors should work, what their responsibilities
      are, how they interact with Skins (if at all, IMHO they
      shouldn't), etc.  Once a design is known and agreed upon, then we
      can work on step-by-step improvements by making parts public, and
      leaving parts hidden.<br>
    </p>
    <span style="font-size:11.0pt;font-family:"Iosevka Fixed
      SS16""></span>
    <p>We really need to think ahead here how Behaviors will work when
      users are allowed to create their own in some future version of
      FX, even if we don't want to put in the work right now to make it
      possible.</p>
    <p>The rest of this post is a similar pattern; API decisions are
      IMHO being justified by existing choices, like Skins would need
      changes, or some control is already doing things in a certain way,
      or things being out of scope (out of scope for implementation is
      fine, but we need to plan ahead so it is not out of scope for the
      design).<br>
    </p>
    <p>IMHO API design comes first, and it needs to think quite far
      ahead, and needs to be incredibly conservative in what it exposes.
      Extracting the API from existing code that does not have a fully
      fleshed out design, and has a lot of open questions is just not
      going to be a good basis for a public API.</p>
    <span style="font-size:11.0pt;font-family:"Iosevka Fixed
      SS16""><o:p> </o:p></span>
    <blockquote type="cite"
cite="mid:DM5PR1001MB21727E4E85D417CE348AF751E5D7A@DM5PR1001MB2172.namprd10.prod.outlook.com">
      <div class="WordSection1">
        <p style="margin-left:.5in"><span
            style="font-family:"Iosevka Fixed SS16""></span>-
          The mutable maps, immutability would allow making these
          static, saving many objects; when I have some time I can take
          a look at how many are in memory when a decent sized FX
          application is running; as even Labels are Controls, and
          Labels are the base class for any Cell, this number might be
          larger than expected and potentially could allow for some
          significant memory savings; making it public as-is closes that
          road down forever.  Immutability does not mean things can't be
          changed, it just requires a slightly different mindset (ie.
          you combine a standard InputMap with a custom InputMap to form
          a new InputMap in which a binding is
          changed/overriden/disabled); this was also proposed on
          JDK-8091189<o:p></o:p></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Saving memory is a noble goal.  You still need
            per-instance InputMap though as we need per-instance key
            mappings.<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">I think delegating the default mappings to a
            separate static input map is still possible, but it will
            require essentially a more extensive re-write of skins and
            therefore is definitely out of scope.</span></p>
      </div>
    </blockquote>
    <br>
    <blockquote type="cite"
cite="mid:DM5PR1001MB21727E4E85D417CE348AF751E5D7A@DM5PR1001MB2172.namprd10.prod.outlook.com">
      <div class="WordSection1">
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal" style="margin-left:.5in">- The Control back
          reference; I firmly believe this is unnecessary, and also very
          undesirable. <span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">It is mostly for convenience of adding key
            bindings directly to the input map with
            registerKey(KeyBinding, FunctionTag).  Other methods also
            use it, I suppose we can get the pointer from behavior, but
            adding the pointer to registerKey raises the issue of what
            if it’s the wrong control, i.e.
            control1.getInputMap().registerKey(control2, ...) ?</span></p>
      </div>
    </blockquote>
    <span style="font-size:11.0pt;font-family:"Iosevka Fixed
      SS16""><o:p> </o:p></span>
    <blockquote type="cite"
cite="mid:DM5PR1001MB21727E4E85D417CE348AF751E5D7A@DM5PR1001MB2172.namprd10.prod.outlook.com">
      <div class="WordSection1">
        <p class="MsoNormal" style="margin-left:.5in">- Not designing
          this using interfaces<o:p></o:p></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">I just don’t think there is a value in adding an
            interface, but one can be introduced easily.</span></p>
      </div>
    </blockquote>
    <span style="font-size:11.0pt;font-family:"Iosevka Fixed
      SS16""><o:p> </o:p></span>
    <blockquote type="cite"
cite="mid:DM5PR1001MB21727E4E85D417CE348AF751E5D7A@DM5PR1001MB2172.namprd10.prod.outlook.com">
      <div class="WordSection1">
        <p class="MsoNormal" style="margin-left:.5in"><span
            style="font-size:12.0pt;color:#212121">- The public
            BehaviorBase and the new public behaviors for many controls;</span><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Two different issues, let’s not bunch them
            together.  BehaviorBase (or an interface with default
            methods) is an important addition and a pre-requisite for
            effective use of the new input map (it’s already being used
            and is a blocker for RichTextArea, and I have one more
            control that needs it).</span></p>
      </div>
    </blockquote>
    <blockquote type="cite"
cite="mid:DM5PR1001MB21727E4E85D417CE348AF751E5D7A@DM5PR1001MB2172.namprd10.prod.outlook.com">
      <div class="WordSection1">
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p><br>
            </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Public concrete behaviors are out of scope at
            this time.</span></p>
      </div>
    </blockquote>
    <blockquote type="cite"
cite="mid:DM5PR1001MB21727E4E85D417CE348AF751E5D7A@DM5PR1001MB2172.namprd10.prod.outlook.com">
      <div class="WordSection1">
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">--<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">It is much more difficult for me to respond to
            the second half of your message.  I do agree with many
            things you’ve said, but all that sounds like a major
            re-design and a re-write to me (I could be wrong).  One
            implicit goal was to retain backward compatibility, and from
            that point of view any major changes are simply unlikely.  <o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">The requirement of backward compatibility (and
            minimization of changes) is is also why I did not introduced
            a parallel method of adding user event handlers.  I suppose
            we
            <u>could</u> add this ability to the InputMap, similarly to
            the way a user-created key binding takes precedence over a
            behavior-created one.  This way we can guarantee that
            user-specified handlers are always invoked before
            behavior-created ones.  This can be bolted on the input map
            as a separate enhancement, I think.<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Let’s discuss the alternative proposal of
            behaviors as translating layers in a separate thread (thank
            you for changing the subject and creating a separate
            thread!).  I feel it’s a more expensive variation of this
            design, but I could be wrong.<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">Thanks again for a very interesting and
            stimulating discussion!  I sincerely hope we can get to an
            agreement soon and move forward.<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16"">-andy<o:p></o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <p class="MsoNormal"><span
            style="font-size:11.0pt;font-family:"Iosevka Fixed
            SS16""><o:p> </o:p></span></p>
        <div id="mail-editor-reference-message-container">
          <div>
            <div style="border:none;border-top:solid #B5C4DF
              1.0pt;padding:3.0pt 0in 0in 0in">
              <p class="MsoNormal" style="margin-bottom:12.0pt"><b><span
                    style="font-size:12.0pt;color:black">From:
                  </span></b><span style="font-size:12.0pt;color:black">John
                  Hendrikx <a class="moz-txt-link-rfc2396E" href="mailto:john.hendrikx@gmail.com"><john.hendrikx@gmail.com></a><br>
                  <b>Date: </b>Saturday, October 14, 2023 at 10:20<br>
                  <b>To: </b>Andy Goryachev
                  <a class="moz-txt-link-rfc2396E" href="mailto:andy.goryachev@oracle.com"><andy.goryachev@oracle.com></a>,
                  <a class="moz-txt-link-abbreviated" href="mailto:openjfx-dev@openjdk.org">openjfx-dev@openjdk.org</a>
                  <a class="moz-txt-link-rfc2396E" href="mailto:openjfx-dev@openjdk.org"><openjfx-dev@openjdk.org></a><br>
                  <b>Subject: </b>Re: [External] : Re: [Request for
                  Comments] Behavior / InputMap<o:p></o:p></span></p>
            </div>
            <div>
              <p class="MsoNormal"><span style="font-size:11.0pt">On
                  12/10/2023 21:56, Andy Goryachev wrote:<o:p></o:p></span></p>
            </div>
            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 "">Filters: are we talking about key
                  bindings or event handlers?  With the key bindings,
                  the user mappings take precedence over those
                  registered through behavior.  There is no provision
                  for adjusting priority of the event handlers – that’s
                  the FX reality, we don’t get to rearrange event
                  handlers within the node.  That’s why I mentioned
                  event filters added
                  <u>to the control</u>.  I am not sure why you talk
                  about HBoxes – adding a filter on the control enables
                  the user to intercept the event prior to
                  skin/behavior.</span><o:p></o:p></p>
            </blockquote>
            <p>On simple Controls yes, filters can be used there for
              this purpose, even though that's not their purpose.  It
              works because a Control (usually) is a leaf node.  It
              breaks down however when you want to change behavior of
              the View controls which have deeper control layers.  You
              may want to override something defined for ListView, but
              only if say a focused editable control isn't consuming
              that event for a different purpose.  A filter won't be
              able to do this.<o:p></o:p></p>
            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 ""> </span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 "">So yes, this proposal does not
                  address the event handlers (sorry for confusing key
                  bindings with event handlers).  Unless we add
                  addListenerBefore() API, we’d need to use event
                  filters – but this is out of scope for this proposal.</span><o:p></o:p></p>
            </blockquote>
            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 ""> </span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 "">I do agree with you that we should
                  keep the concrete Behaviors private for now.  In any
                  case, public behaviors are outside of scope for this
                  proposal.</span><o:p></o:p></p>
            </blockquote>
            <p>I see BehaviorBase moving to a public package though, and
              it is not package private, is that intended then?<o:p></o:p></p>
            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 ""> </span><o:p></o:p></p>
              <p class="MsoNormal" style="margin-bottom:12.0pt"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 "">One thing you mentioned several
                  times is a “truly good design”.  Let’s hear it!  Could
                  you give us an outline, at the public API level at
                  least, of such a design?</span><o:p></o:p></p>
            </blockquote>
            <p>Alright; these things take a lot of time, but I've taken
              a few hours to think about it today. First, a lot of
              things just triggered me with the current proposal;<o:p></o:p></p>
            <p>- The mutable maps, immutability would allow making these
              static, saving many objects; when I have some time I can
              take a look at how many are in memory when a decent sized
              FX application is running; as even Labels are Controls,
              and Labels are the base class for any Cell, this number
              might be larger than expected and potentially could allow
              for some significant memory savings; making it public
              as-is closes that road down forever.  Immutability does
              not mean things can't be changed, it just requires a
              slightly different mindset (ie. you combine a standard
              InputMap with a custom InputMap to form a new InputMap in
              which a binding is changed/overriden/disabled); this was
              also proposed on JDK-8091189<o:p></o:p></p>
            <p>- The Control back reference; I firmly believe this is
              unnecessary, and also very undesirable.  Events already
              contain this reference, its superflous and requires a new
              instance for an (otherwise) similar instance; This is even
              done already in places, exactly to avoid having to create
              more instances (see #getNode in FocusTraversalInputMap for
              example, effectively allowing that class to be static
              while providing the focus traversal behavior).   This was
              also raised on JDK-8091189<o:p></o:p></p>
            <p>- Not designing this using interfaces (also raised on
              JDK-8091189).  With the addition of default methods, we
              should favor composable designs instead of being forced to
              inherit from a base class in order to provide a custom
              implementation.  Sure, you can still provide a default
              implementation, but public methods should be referring to
              the interface so it can be a completely different
              implementation.  Interfaces prevent using package private
              shortcuts where privileged classes can provide a
              functionality that users cannot.<o:p></o:p></p>
            <p>- The public BehaviorBase and the new public behaviors
              for many controls; I'm not convinced behaviors (if we
              can't define exactly what their purpose is supposed to be
              vs the Control and Skin) are ready to become more than
              just an implementation detail.<o:p></o:p></p>
            <p>As for high level design, it of course depends on what
              the goal here is.  The issues linked in the proposal all
              call out for a public behavior API, but your proposal
              narrows the scope rightfully down to influencing default
              reactions to (key?) events only.  Making behaviors public
              as they are now, and without a clear definition of what
              they are, seems definitely premature.  I think they first
              need to be re-evaluated to see if they are still a good
              design at all (after all they're 10+ years old), then
              rewritten internally (if the ideas behind them changed),
              and only then made public.<o:p></o:p></p>
            <p>In your proposal I think the Summary and Motivation are
              quite good at outlining a problem to be solved.  I'd like
              to rephrase that as a goal: "To allow developers to remap,
              override or disable the standard behavior of JavaFX
              controls (note: behavior here is used in the general
              sense)".  I think there is no need to mention InputMap,
              Behaviors or key bindings here, those are merely possible
              means to achieve the goal.<o:p></o:p></p>
            <p>I'd then first take a look how this could be achieved
              with current JavaFX, and where users are running into a
              wall.<o:p></o:p></p>
            <p>Most obviously, the way to make controls do something you
              want is by using event handlers.  Even Behaviors use these
              internally, in which we'll later see lies a bit of the
              problem.<br>
              <br>
              # Expectations<o:p></o:p></p>
            <p>Just like when a developer sets a Control property
              directly to a specific value, when the developers adds an
              event handler or listener, he/she can rightfully expect
              that FX respects this and does not get in the way.  For
              the property case, CSS will not override such a property,
              for listeners, all listeners receive any callbacks, and
              for events, the user registered handlers should take
              priority over internal handlers (unlike listeners, event
              handlers can consume and act upon events before they reach
              the user handler, hence order plays an important role
              here).<o:p></o:p></p>
            <p>CSS, Skins and Behaviors sharing the same properties,
              listeners and event handlers with application developers
              has always been a bit of a balancing act; CSS has an
              elaborate system to respect user property changes, and
              keeps track of these; Skins for the most part manage to
              stay out of the application developer's way, mostly
              because they primarily use listeners which inherently
              don't block listeners added by the application developer. 
              They also rarely override properties outright that are
              also modifiable by the developer.<o:p></o:p></p>
            <p>With Behaviors the situation is very different.  Event
              handlers added by behaviors will consume events,
              effectively acting upon them before the application
              developer can (you may still see such events as
              "consumed", but they will not bubble up further). On top
              of that is the fact that EventHandlers are far more
              complicated than plain listeners or properties.  For
              example, a KeyEvent.KEY_PRESSED handler is called before a
              KeyEvent.KEY_ANY handler; attempting to override behavior
              in a KeyEvent.KEY_ANY handler is therefore impossible when
              the behavior to override is using a more specific event
              type.  Consumption of an event only blocks
              capturing/bubbling of the event; other event handlers at
              the same level do still see such events, but they're
              marked "consumed"; most event handlers should therefore
              probably start with a `if (e.isConsumed()) return` line,
              but often don't (users often don't do this because they
              expect their handlers to be the only ones present, or to
              be called first, even though for Controls with Behaviors
              this is not actually true).<o:p></o:p></p>
            <p># Problems<o:p></o:p></p>
            <p>Some of the problems you can expect to see when you want
              to act upon an event that has a "default" behavior (versus
              ones that don't):<o:p></o:p></p>
            <p>- Adding a more generic event handler than the one used
              internally will result in the events you are interested in
              being consumed already<br>
              - Adding the exact same event handler as one used
              internally AFTER the control was shown (or re-adding it in
              response to something) will result in events you are
              interested in being consumed already, or more generally,
              an event handler works differently whether they were added
              before or after the control was shown...<br>
              - Events for which there exist a default behavior are in
              some cases consumed even if the behavior could not be
              performed (navigation)<br>
              <br>
              In all the above cases, for events WITHOUT default
              behavior, such a user installed handler works exactly as
              expected. IMHO there really should be no difference for
              the user whether there is a default behavior or not.<o:p></o:p></p>
            <p># Causes<o:p></o:p></p>
            <p>Almost all of these problems are caused by the fact that
              JavaFX's internal handlers share the same lists/mechanisms
              as application developers to react to events; these
              internal handlers are mixed up with event handlers from
              application developers; often the internal ones run first,
              but it is very unpredictable:<o:p></o:p></p>
            <p>- Is your event handler more generic than an internal
              handler?  You always run last<br>
              - Is your event handler more specific than an internal
              handler?  You always run first<br>
              - Is your event handler the exact same event type as an
              internal handler... then:<br>
                 - Did you add handlers before the control was shown /
              skin was created? Yours run first (subject to change no
              doubt, we don't guarantee this)<br>
                 - Did you add handlers after the control was shown?
              Yours run last (no guarantees)<br>
                 - Did you add handlers after the control was shown, but
              then its skin was replaced?  Your event handlers that used
              to run last now run first... (undocumented)<br>
              <br>
              An innocent change like listening for KeyEvent.ANY vs
              KeyEvent.KEY_PRESSED can have big repercussions.<o:p></o:p></p>
            <p># How to reach the goal?<o:p></o:p></p>
            <p>There are many ways to reach the above stated goal. 
              Opening up some internal structures that are used by the
              internal event handlers is one way, but it effectively
              creates a 2nd mechanism to do the same thing.  I can
              change the internal event handler's internal structures to
              do X, or I can create an event handler that does X.  For
              some of these, both options work, and for others, only
              this new mechanism works.   Not only is this mostly
              compensating for a flaw in the event handling system, but
              it also means that you need to be aware of which events
              need special treatment. It's even possible that some
              events require no special treatment now, but may in the
              future, or may need it if the platform changes certain
              defaults. In other words, this new mechanism would
              effectively need to be used in all cases or you risk your
              solution (using standard event handlers) breaking in the
              future (or JavaFX would have to freeze input maps and
              never change them again -- that's already sort of the
              case, but it is good to be aware of that).<o:p></o:p></p>
            <p># Alternative solution<o:p></o:p></p>
            <p>I would look into seeing if the flaws in the event
              handling system can be resolved, so that this mechanism
              that is already available, and that users already know
              becomes powerful enough to cater to the stated goal.  Note
              that this doesn't preclude opening up behaviors later, but
              it does take away one of the fundamental reasons to do so,
              perhaps allowing for quite a different way of exposing
              these to users as the primary driver need no longer be
              focused on remapping bindings.  Perhaps the primary driver
              can then be how to design behaviors in such a way that
              they can be re-used and easily subclassed; perhaps
              behaviors are no longer needed at all, and they can remain
              an internal implementation detail, or perhaps they can be
              part of skins or controls.<o:p></o:p></p>
            <p>I see a few problems that should be addressed if we want
              to be able to reach the goal with better event handlers:<o:p></o:p></p>
            <p>1) Internal event handlers should NOT use the same
              mechanism as user event handlers; effectively, user event
              handlers (of any event type, even more general ones) run
              first, as if no internal event handlers existed at all. 
              This is already the case depending on the timing of when
              the user added the handlers; the timing is unpredictable
              (as stated above) and so I think we have enough leeway to
              change this, and enough reason to tighten up the
              specification here.<o:p></o:p></p>
            <p>2) All internal event handlers run AFTER user ones (per
              EventTarget), regardless of when they were added. A
              separate list can be used, or the event type system could
              support this with some kind of internal flag.<o:p></o:p></p>
            <p>3) Internal event handlers can be skipped completely if
              the user marks an event as such.  This is different from
              consuming the event; effectively, the event is not
              consumed (and can bubble up to other event targets) but
              internal event handlers are not allowed to act upon it.<o:p></o:p></p>
            <p>4) All actions triggered by behaviors should be available
              as public methods (nested or direct) on their respective
              controls, allowing the user to call these as well.<o:p></o:p></p>
            <p>The above changes should be enough to support the stated
              goal: "To allow developers to remap, override or disable
              the standard behavior of JavaFX controls (note: behavior
              here is used in the general sense)"<o:p></o:p></p>
            <p>To override a standard behavior: install event handler
              (which will run first), react to an event, call a public
              method triggering the DIFFERENT behavior, consume the
              event<br>
              To disable a standard behavior: install event handler,
              react to an event, mark it as "not for internal use",
              effectively disallowing the internal handlers from acting
              on it<br>
              To remap a standard behavior: combine the above two
              solutions<o:p></o:p></p>
            <p># New API needed<o:p></o:p></p>
            <p>A flag on `Event` that can be set/cleared whenever the
              user wants.  The flag effectively communicates that the
              given event is not to be processed by the "hidden"
              internal event handlers added by JavaFX.  It could be
              called "noDefault" or "skipDefaultBehavior".<o:p></o:p></p>
            <p>Depending on the internal changes needed to separate user
              event handlers from internal ones, EventType may also need
              a small change.  For example, if the separation is
              implemented by introducing more event types, a convenient
              `EventType#toInternal` method could be added to convert a
              regular event type to an internal one that is always
              processed after standard ones.  It's possible such a
              method does not need to be public (but could be if users
              desire the old unpredictable behavior of mixing user and
              internal event handlers).<o:p></o:p></p>
            <p># Alternative alternative solution<o:p></o:p></p>
            <p>Part of the problem can also be solved by disallowing
              internal handlers to listen on the most specific EventType
              (ie, don't listen to KeyEvent.KEY_PRESSED, but instead
              listen to KeyEvent.ANY).  This way a user can be the first
              to handle the event in all cases by using a more specific
              type (KeyEvent.KEY_PRESSED) or the last in all cases by
              using a less specific type (InputEvent.ANY).  This leaves
              much to be desired, and doesn't solve all of the above
              outlined problems, but I mention it to show that there is
              quite a lot possible here already by tweaking the event
              handling system.<o:p></o:p></p>
            <p>--John<o:p></o:p></p>
            <p><o:p> </o:p></p>
            <blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 ""> </span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 "">Thank you</span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 "">-andy</span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 ""> </span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 ""> </span><o:p></o:p></p>
              <p class="MsoNormal"><span
                  style="font-size:11.0pt;font-family:"Iosevka
                  Fixed SS16 ""> </span><o:p></o:p></p>
              <div id="mail-editor-reference-message-container">
                <div>
                  <div style="border:none;border-top:solid #B5C4DF
                    1.0pt;padding:3.0pt 0in 0in 0in">
                    <p class="MsoNormal" style="margin-bottom:12.0pt"><b><span
                          style="font-size:12.0pt;color:black">From:
                        </span></b><span
                        style="font-size:12.0pt;color:black">John
                        Hendrikx <a
                          href="mailto:john.hendrikx@gmail.com"
                          moz-do-not-send="true">
                          <john.hendrikx@gmail.com></a><br>
                        <b>Date: </b>Thursday, October 12, 2023 at
                        01:33<br>
                        <b>To: </b>Andy Goryachev <a
                          href="mailto:andy.goryachev@oracle.com"
                          moz-do-not-send="true"><andy.goryachev@oracle.com></a>,
                        <a href="mailto:openjfx-dev@openjdk.org"
                          moz-do-not-send="true"
                          class="moz-txt-link-freetext">openjfx-dev@openjdk.org</a>
                        <a href="mailto:openjfx-dev@openjdk.org"
                          moz-do-not-send="true">
                          <openjfx-dev@openjdk.org></a><br>
                        <b>Subject: </b>[External] : Re: [Request for
                        Comments] Behavior / InputMap</span><o:p></o:p></p>
                  </div>
                  <p> <o:p></o:p></p>
                  <div>
                    <p class="MsoNormal"><span style="font-size:11.0pt">On
                        11/10/2023 19:44, Andy Goryachev wrote:</span><o:p></o:p></p>
                  </div>
                  <blockquote
                    style="margin-top:5.0pt;margin-bottom:5.0pt">
                    <p class="MsoNormal"><span
                        style="font-size:11.0pt;font-family:"Iosevka
                        Fixed SS16 "">Dear John:</span><o:p></o:p></p>
                    <p class="MsoNormal"><span
                        style="font-size:11.0pt;font-family:"Iosevka
                        Fixed SS16 ""> </span><o:p></o:p></p>
                    <p class="MsoNormal"><span
                        style="font-size:11.0pt;font-family:"Iosevka
                        Fixed SS16 "">Seems like addEventFilter()
                        was specifically designed to intercept events
                        before any other handlers, so I see no problem
                        there.</span><o:p></o:p></p>
                  </blockquote>
                  <p>This is a misunderstanding of what filters are
                    for.  They're called in the capturing phase and they
                    can prevent an event from reaching its intended
                    target, but you want it to reach the intended target
                    FIRST, as you still want to give the target the
                    chance to be the first to act upon the event.  For
                    example, let's say I want to attach a function to
                    the SPACE key in some specialized HBox, it should
                    only do something when something closer to the
                    target doesn't need it first (like a nested HBox of
                    the same type, or an active TextField that uses
                    SPACE for input).  Now if HBox had some FX default
                    event handler that consumed SPACE, I have no options
                    to override SPACE anymore; the filter is not a good
                    spot, as its too early, and the handler is not a
                    good spot because Behavior handlers were added
                    before mine was.<o:p></o:p></p>
                  <p class="MsoNormal"><br>
                    <span style="font-size:11.0pt"><br>
                      <br>
                    </span><o:p></o:p></p>
                  <blockquote
                    style="margin-top:5.0pt;margin-bottom:5.0pt">
                    <p class="MsoNormal"><span
                        style="font-size:11.0pt;font-family:"Iosevka
                        Fixed SS16 ""> </span><o:p></o:p></p>
                    <p class="MsoNormal"><span
                        style="font-size:11.0pt;font-family:"Iosevka
                        Fixed SS16 "">I somewhat disagree about the
                        purpose of the key mapping system – the proposed
                        solution solves two existing issues (the
                        skin/behavior mappings and the user mappings) in
                        one neat package.  Every other instrument such
                        as addEventHandler/Filter is still there.</span><o:p></o:p></p>
                  </blockquote>
                  <p>I'm saying that the need for this would be almost
                    non-existent if user event handlers weren't
                    considered less important than FX ones. You have to
                    be careful that there aren't two ways of doing
                    things here:<o:p></o:p></p>
                  <p>If the event you wish to give an alternative
                    purpose to is unused by FX, you can use an event
                    handler; otherwise you must disable it (so you can
                    use an event handler!) or remap it (using an
                    alternative system).  Note that if FX at some point
                    decides to "claim" another mapping, that would be a
                    breaking change as some user event handlers may
                    cease to function.<o:p></o:p></p>
                  <p>This is why I think the input mapping system should
                    stay hidden; its an implementation detail of the
                    Event handlers added by FX so they don't need to
                    write long if/else/switch chains, and so they can
                    more easily switch out mappings depending on state. 
                    Opening up the input map effectively is being able
                    to influence those FX added event handlers to do
                    something different, while there is a perfectly good
                    way of doing that already: add your own event
                    handler (with higher priority).<o:p></o:p></p>
                  <blockquote
                    style="margin-top:5.0pt;margin-bottom:5.0pt">
                    <p class="MsoNormal"><span
                        style="font-size:11.0pt;font-family:"Iosevka
                        Fixed SS16 ""> </span><o:p></o:p></p>
                    <p class="MsoNormal"><span
                        style="font-size:11.0pt;font-family:"Iosevka
                        Fixed SS16 "">And, if we look at the three
                        bullet points</span><o:p></o:p></p>
                    <p class="MsoNormal"><span
                        style="font-size:11.0pt;font-family:"Iosevka
                        Fixed SS16 ""> </span><o:p></o:p></p>
                    <p style="margin-left:.5in">- Ensure user event
                      handlers have priority over behavior/inputmap
                      added ones<br>
                      - Ensure all behavior actions are available as
                      methods on controls<br>
                      - Ensure that if a key is handled by the control,
                      that it is ONLY consumed when it actually triggers
                      an action (navigation keys get consumed
                      regardless, even if no focus change results,
                      that's wrong).<o:p></o:p></p>
                    <p class="MsoNormal"><span
                        style="font-size:11.0pt;font-family:"Iosevka
                        Fixed SS16 "">I absolutely agree, and in
                        fact the first three are indeed a part of the
                        proposal.  Well, the 3<sup>rd</sup> one might
                        unfortunately be a subject of backward
                        compatibility limitation since one of the
                        requirements was no behavior change w.r.t. the
                        earlier versions.  We can always change the
                        behavior if we have a completing reason and go
                        through the usual process, nothing in the
                        proposal precludes that.</span><o:p></o:p></p>
                  </blockquote>
                  <p>I don't see how your proposal addresses the first
                    point.  <o:p></o:p></p>
                  <p>I've been reading the comments attached to <a
                      href="https://bugs.openjdk.org/browse/JDK-8091189"
                      moz-do-not-send="true"
                      class="moz-txt-link-freetext">
                      https://bugs.openjdk.org/browse/JDK-8091189</a>
                    and it has a lot of good information, and raises
                    many good points (immutable input maps, keep input
                    maps/behaviors as implementation details, use
                    interfaces instead of base classes, what about
                    controls that have no Skin, even the point I made
                    about having the Control be in charge of registering
                    the event handlers instead of letting InputMap do it
                    requiring a Control field...).  There are several
                    patches by Jonathan Giles, and there is even a
                    library created by the author of ReactFX that allows
                    for replacing key bindings with a much nicer API
                    already (in so far that is possible without having
                    inside FX support). 
                    <o:p></o:p></p>
                  <p>The general tone of the comments seems to be that
                    Behaviors should be kept as implementation details
                    -- they're not well defined (what is a Behavior,
                    what should be in the Behavior, what should be in
                    the Skin and what should be in the Control) and
                    until that is absolutely clear, exposing any of that
                    as API is premature.  <o:p></o:p></p>
                  <blockquote
                    style="margin-top:5.0pt;margin-bottom:5.0pt">
                    <p class="MsoNormal"><span
                        style="font-size:11.0pt;font-family:"Iosevka
                        Fixed SS16 ""> </span><o:p></o:p></p>
                    <p class="MsoNormal"><span
                        style="font-size:11.0pt;font-family:"Iosevka
                        Fixed SS16 "">Making the behaviors
                        completely independent with setBehavior() and
                        FXML, as you said, might be a future effort,
                        perhaps we could attempt opening up certain
                        controls at some point.  On one hand, I am for
                        increasing the extensibility of FX, on the other
                        hand the same argument can be made against it
                        (as in solidifying a particular way of
                        constructing skins and behaviors), but I feel
                        it’s a separate issue that is independent of
                        this proposal.</span><o:p></o:p></p>
                  </blockquote>
                  <p>I'm starting to lean towards keeping all of this as
                    implementation details, at least until the current
                    implementation is much cleaner than it is currently
                    (the way InputMap and Behaviors currently are set up
                    is more pragmatic than truly a good design), and
                    just address the main issue: JavaFX stealing events
                    that users want to override, note that I say events,
                    key bindings are only part of it.<o:p></o:p></p>
                  <p>--John<o:p></o:p></p>
                  <blockquote
                    style="margin-top:5.0pt;margin-bottom:5.0pt">
                    <p class="MsoNormal"><span
                        style="font-size:11.0pt;font-family:"Iosevka
                        Fixed SS16 ""> </span><o:p></o:p></p>
                    <p class="MsoNormal"><span
                        style="font-size:11.0pt;font-family:"Iosevka
                        Fixed SS16 ""> </span><o:p></o:p></p>
                    <p class="MsoNormal"><span
                        style="font-size:11.0pt;font-family:"Iosevka
                        Fixed SS16 "">-andy</span><o:p></o:p></p>
                    <p class="MsoNormal"><span
                        style="font-size:11.0pt;font-family:"Iosevka
                        Fixed SS16 ""> </span><o:p></o:p></p>
                    <p class="MsoNormal"><span
                        style="font-size:11.0pt;font-family:"Iosevka
                        Fixed SS16 ""> </span><o:p></o:p></p>
                    <p class="MsoNormal"><span
                        style="font-size:11.0pt;font-family:"Iosevka
                        Fixed SS16 ""> </span><o:p></o:p></p>
                    <div id="mail-editor-reference-message-container">
                      <div>
                        <div style="border:none;border-top:solid #B5C4DF
                          1.0pt;padding:3.0pt 0in 0in 0in">
                          <p class="MsoNormal"
                            style="margin-bottom:12.0pt"><b><span
                                style="font-size:12.0pt;color:black">From:
                              </span></b><span
                              style="font-size:12.0pt;color:black">openjfx-dev
                              <a
                                href="mailto:openjfx-dev-retn@openjdk.org"
                                moz-do-not-send="true">
                                <openjfx-dev-retn@openjdk.org></a>
                              on behalf of John Hendrikx <a
                                href="mailto:john.hendrikx@gmail.com"
                                moz-do-not-send="true">
                                <john.hendrikx@gmail.com></a><br>
                              <b>Date: </b>Wednesday, October 11, 2023
                              at 01:04<br>
                              <b>To: </b><a
                                href="mailto:openjfx-dev@openjdk.org"
                                moz-do-not-send="true"
                                class="moz-txt-link-freetext">openjfx-dev@openjdk.org</a>
                              <a href="mailto:openjfx-dev@openjdk.org"
                                moz-do-not-send="true">
                                <openjfx-dev@openjdk.org></a><br>
                              <b>Subject: </b>Re: [Request for
                              Comments] Behavior / InputMap</span><o:p></o:p></p>
                        </div>
                        <p>I'm sorry, but that providing an arbitrary
                          key mapping system seems completely out of
                          scope and not something that JavaFX should
                          concern itself with.  It's much too high
                          level, when the key mappings involved should
                          only be for actions that the control can
                          provide on its own.<o:p></o:p></p>
                        <p class="MsoNormal"><span
                            style="font-size:11.0pt">I think the problem
                            we should be solving is that JavaFX control
                            behaviors shouldn't be first in line when it
                            comes to consuming events (which currently
                            is only the case due to event handlers being
                            added at the earliest possible opportunity,
                            and event handlers being called in order). 
                            If something as trivial as:
                          </span><o:p></o:p></p>
                        <p>      
                          control.addEventHandler(KeyEvent.KEY_PRESSED,
                          e -> {<br>
                                        if (e.getCode() == KeyCode.LEFT)
                          {<br>
                                              e.consume();  // stop
                          default behavior<br>
                                        }<br>
                                 });<o:p></o:p></p>
                        <p>... actually worked, then there is much less
                          need to redefine/disable behavior key
                          mappings, and no need for a secondary system
                          that deals with mappings (the first system,
                          event handlers, can simply be used for this). 
                          If user event handlers had priority over
                          behavior ones, then everything you want can be
                          achieved with the above, including:<o:p></o:p></p>
                        <p>- Stopping default behavior<br>
                          - Triggering different behavior (just call
                          something on control, of course, make sure all
                          behavior actions are available on the control
                          in the first place)<br>
                          - Remapping (a combination of the above two)<br>
                          - Adding an alternative key for the same
                          behavior<o:p></o:p></p>
                        <p>A system to remap keys can then be left
                          squarely in the realm of user space, and much
                          nicer solutions can be build by users than
                          whatever JavaFX will provide out of the box.<o:p></o:p></p>
                        <p>Changes to the Behavior system can then focus
                          on replacing complete behaviors (including
                          their input map) and being able to use these
                          by default for a certain subset of controls
                          (like -fx-skin provide in CSS), as this is
                          something users currently can't do.<o:p></o:p></p>
                        <p>So in short, what I think this should be
                          about is:<o:p></o:p></p>
                        <p>- Ensure user event handlers have priority
                          over behavior/inputmap added ones<br>
                          - Ensure all behavior actions are available as
                          methods on controls<br>
                          - Ensure that if a key is handled by the
                          control, that it is ONLY consumed when it
                          actually triggers an action (navigation keys
                          get consumed regardless, even if no focus
                          change results, that's wrong).<o:p></o:p></p>
                        <p>Future:<o:p></o:p></p>
                        <p>- Make behaviors public and allow Behaviors
                          to be replaced with -fx-behavior type CSS
                          syntax / control.setBehavior calls<o:p></o:p></p>
                        <p>--John<o:p></o:p></p>
                        <p> <o:p></o:p></p>
                        <p>The focus should be on being able to modify
                          standard behavior of controls (arrow-left,
                          enter, ctrl-shift-right, etc.), specifically
                          also to be able to disable these when
                          undesired, and, on top of that, that they
                          bubble up when NOT used even when they are
                          configured (focus navigation keys currently
                          are always consumed, whether they actually do
                          something or not -- that's a big issue).  The
                          other focus should be on providing an
                          alternative behavior (or at least mappings)
                          for all controls of a certain type -- I don't
                          see the need for adding a mapping to a
                          specific control, that's already covered with
                          event handlers; the problem is mostly that
                          behaviors currently steal certain events
                          before the user can get at them.<o:p></o:p></p>
                        <p>Custom behaviors can then be constructed that
                          provide more things that may need mapping. 
                          I'd expect those however to be limited in
                          scope to what the control offers, certainly
                          not an arbitrary key/action mapping system
                          (that wouldn't even work, as most of these
                          would be in the scope of several controls or
                          be global).  This kind of functionality is
                          much better provided by event handlers at the
                          correct level for a group of controls, and I
                          wouldn't expect to find such an eloborate
                          system incorporated in behaviors.<o:p></o:p></p>
                        <p>In fact, thinking about all of this a bit
                          more, <o:p></o:p></p>
                        <p> <o:p></o:p></p>
                        <p>On 10/10/2023 19:54, Andy Goryachev wrote:<o:p></o:p></p>
                        <blockquote
                          style="margin-top:5.0pt;margin-bottom:5.0pt">
                          <p class="MsoNormal"><span
                              style="font-size:11.0pt;font-family:"Iosevka
                              Fixed SS16 "">Re-sending with a
                              smaller image (256kb limit, really?).</span><o:p></o:p></p>
                          <p class="MsoNormal"><span
                              style="font-size:11.0pt;font-family:"Iosevka
                              Fixed SS16 ""> </span><o:p></o:p></p>
                          <div
                            id="mail-editor-reference-message-container">
                            <div>
                              <div style="border:none;border-top:solid
                                #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
                                <p class="MsoNormal"
                                  style="margin-bottom:12.0pt"><b><span
style="font-size:12.0pt;color:black">From:
                                    </span></b><span
                                    style="font-size:12.0pt;color:black">Andy
                                    Goryachev <a
                                      href="mailto:andy.goryachev@oracle.com"
                                      moz-do-not-send="true">
                                      <andy.goryachev@oracle.com></a><br>
                                    <b>Date: </b>Tuesday, October 10,
                                    2023 at 10:49<br>
                                    <b>To: </b>Michael Strauß <a
                                      href="mailto:michaelstrau2@gmail.com"
                                      moz-do-not-send="true"><michaelstrau2@gmail.com></a><br>
                                    <b>Cc: </b><a
                                      href="mailto:openjfx-dev@openjdk.org"
                                      moz-do-not-send="true"
                                      class="moz-txt-link-freetext">openjfx-dev@openjdk.org</a>
                                    <a
                                      href="mailto:openjfx-dev@openjdk.org"
                                      moz-do-not-send="true">
                                      <openjfx-dev@openjdk.org></a><br>
                                    <b>Subject: </b>Re: [Request for
                                    Comments] Behavior / InputMap</span><o:p></o:p></p>
                              </div>
                              <p class="MsoNormal"><span
                                  style="font-size:11.0pt;font-family:"Iosevka
                                  Fixed SS16 "">Dear Michael:</span><o:p></o:p></p>
                              <p class="MsoNormal"><span
                                  style="font-size:11.0pt;font-family:"Iosevka
                                  Fixed SS16 ""> </span><o:p></o:p></p>
                              <p class="MsoNormal"><span
                                  style="font-size:11.0pt;font-family:"Iosevka
                                  Fixed SS16 "">Here is a use case
                                  for (re-)mapping by the user at
                                  runtime:</span><o:p></o:p></p>
                              <p class="MsoNormal"><span
                                  style="font-size:11.0pt;font-family:"Iosevka
                                  Fixed SS16 ""> </span><o:p></o:p></p>
                              <p class="MsoNormal"><img
                                  style="width:8.052in;height:6.8333in"
                                  id="Picture_x0020_2"
                                  src="cid:part1.Red2Hqmj.6LY70vxB@gmail.com"
                                  class="" width="773" height="656"
                                  border="0"><o:p></o:p></p>
                              <p class="MsoNormal"><span
                                  style="font-size:11.0pt;font-family:"Iosevka
                                  Fixed SS16 ""> </span><o:p></o:p></p>
                              <p class="MsoNormal"><span
                                  style="font-size:11.0pt;font-family:"Iosevka
                                  Fixed SS16 "">(key mappings UI in
                                  Eclipse).</span><o:p></o:p></p>
                              <p class="MsoNormal"><span
                                  style="font-size:11.0pt;font-family:"Iosevka
                                  Fixed SS16 ""> </span><o:p></o:p></p>
                              <p class="MsoNormal"><span
                                  style="font-size:11.0pt;font-family:"Iosevka
                                  Fixed SS16 "">I can think of
                                  several other cases (mentioned in the
                                  proposal, I think) so I think we can
                                  put the concept of immutable or global
                                  InputMap to rest.</span><o:p></o:p></p>
                              <p class="MsoNormal"><span
                                  style="font-size:11.0pt;font-family:"Iosevka
                                  Fixed SS16 ""> </span><o:p></o:p></p>
                              <p class="MsoNormal"><span
                                  style="font-size:11.0pt;font-family:"Iosevka
                                  Fixed SS16 "">Whether the
                                  InputMap contains the reference to its
                                  control or not is a minor
                                  implementation detail, I think.</span><o:p></o:p></p>
                              <p class="MsoNormal"><span
                                  style="font-size:11.0pt;font-family:"Iosevka
                                  Fixed SS16 ""> </span><o:p></o:p></p>
                              <p class="MsoNormal"><span
                                  style="font-size:11.0pt;font-family:"Iosevka
                                  Fixed SS16 "">-andy</span><o:p></o:p></p>
                              <p class="MsoNormal"><span
                                  style="font-size:11.0pt;font-family:"Iosevka
                                  Fixed SS16 ""> </span><o:p></o:p></p>
                              <p class="MsoNormal"><span
                                  style="font-size:11.0pt;font-family:"Iosevka
                                  Fixed SS16 ""> </span><o:p></o:p></p>
                              <div
                                id="mail-editor-reference-message-container">
                                <div>
                                  <div
                                    style="border:none;border-top:solid
                                    #B5C4DF 1.0pt;padding:3.0pt 0in 0in
                                    0in">
                                    <p class="MsoNormal"
                                      style="margin-bottom:12.0pt"><b><span
style="font-size:12.0pt;color:black">From:
                                        </span></b><span
                                        style="font-size:12.0pt;color:black">openjfx-dev
                                        <a
                                          href="mailto:openjfx-dev-retn@openjdk.org"
                                          moz-do-not-send="true">
<openjfx-dev-retn@openjdk.org></a> on behalf of Michael Strauß <a
href="mailto:michaelstrau2@gmail.com" moz-do-not-send="true">
<michaelstrau2@gmail.com></a><br>
                                        <b>Date: </b>Tuesday, October
                                        10, 2023 at 10:36<br>
                                        <b>To: </b><br>
                                        <b>Cc: </b><a
                                          href="mailto:openjfx-dev@openjdk.org"
                                          moz-do-not-send="true"
                                          class="moz-txt-link-freetext">openjfx-dev@openjdk.org</a>
                                        <a
                                          href="mailto:openjfx-dev@openjdk.org"
                                          moz-do-not-send="true">
<openjfx-dev@openjdk.org></a><br>
                                        <b>Subject: </b>Re: [Request
                                        for Comments] Behavior /
                                        InputMap</span><o:p></o:p></p>
                                  </div>
                                  <div>
                                    <p class="MsoNormal"><span
                                        style="font-size:11.0pt">>
                                        Yes, one of the features the new
                                        design provides is ability to
                                        modify key mappings by the user
                                        at runtime.  So yes, not only it
                                        needs to be mutable, but it also
                                        adds some APIs for exactly that.<br>
                                        ><br>
                                        <br>
                                        I struggle to see a use case for
                                        this feature. I can imagine that<br>
                                        there might be some use cases
                                        that call for customized input
                                        mappings,<br>
                                        but why would this translate to
                                        a _mutable_ input map? That's
                                        quite a<br>
                                        departure from the way other
                                        parts of JavaFX work.<br>
                                        <br>
                                        For example, skins are also
                                        immutable. If you want to have a
                                        different<br>
                                        skin for a control, you don't
                                        somehow modify the existing skin<br>
                                        instance; instead, you'd create
                                        a new skin class (or -- somehow
                                        --<br>
                                        extend an existing skin class),
                                        and then install that new skin
                                        on your<br>
                                        control.<br>
                                        <br>
                                        An input map shouldn't bind
                                        input events directly to
                                        instance methods<br>
                                        of a particular control
                                        instance. It should define the
                                        mapping of<br>
                                        events to methods symbolically:<br>
                                        <br>
                                        Instead of mapping Event =>
                                        instance.method(), it should map
                                        Event =><br>
                                        Control::method. The input map
                                        could then be stateless and
                                        immutable,<br>
                                        and can be set on any control
                                        instance. If you want to change
                                        the<br>
                                        mappings, just set a different
                                        input map instance. There's no
                                        need<br>
                                        that an input map would retain a
                                        reference to any particular
                                        control,<br>
                                        since the control reference can
                                        be passed into the input map
                                        just as<br>
                                        easily.</span><o:p></o:p></p>
                                  </div>
                                </div>
                              </div>
                            </div>
                          </div>
                        </blockquote>
                      </div>
                    </div>
                  </blockquote>
                </div>
              </div>
            </blockquote>
          </div>
        </div>
      </div>
    </blockquote>
  </body>
</html>