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