<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:Wingdings;
        panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 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:"Helvetica Neue";
        panose-1:2 0 5 3 0 0 0 2 0 4;}
/* Style Definitions */
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.EmailStyle18
        {mso-style-type:personal-reply;
        font-family:"Courier New";
        color:windowtext;}
span.s1
        {mso-style-name:s1;
        font-family:"Helvetica Neue";}
span.s2
        {mso-style-name:s2;
        font-family:"Helvetica Neue";
        color:#DCA10D;}
p.li1, li.li1, div.li1
        {mso-style-name:li1;
        margin:0in;
        font-size:10.0pt;
        font-family:"Helvetica Neue";}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;
        mso-ligatures:none;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
/* List Definitions */
@list l0
        {mso-list-id:566116522;
        mso-list-template-ids:305974756;}
@list l0:level1
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Symbol;}
@list l0:level2
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:1.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:"Courier New";
        mso-bidi-font-family:"Times New Roman";}
@list l0:level3
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:1.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Wingdings;}
@list l0:level4
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Wingdings;}
@list l0:level5
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:2.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Wingdings;}
@list l0:level6
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Wingdings;}
@list l0:level7
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:3.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Wingdings;}
@list l0:level8
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.0in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Wingdings;}
@list l0:level9
        {mso-level-number-format:bullet;
        mso-level-text:;
        mso-level-tab-stop:4.5in;
        mso-level-number-position:left;
        text-indent:-.25in;
        mso-ansi-font-size:10.0pt;
        font-family:Wingdings;}
ol
        {margin-bottom:0in;}
ul
        {margin-bottom:0in;}
--></style>
</head>
<body lang="EN-US" link="blue" vlink="purple" style="word-wrap:break-word">
<div class="WordSection1">
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New"">I agree that focus management is one of the less developed parts of JavaFX.  In addition to all the scenarios listed by John and Chuck, there is a case where input is accepted by
 two controls at the same time<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New""><o:p> </o:p></span></p>
<ul style="margin-top:0in" type="disc">
<li class="li1" style="mso-list:l0 level1 lfo1"><span class="s1"><span style="font-size:9.0pt"><a href="https://bugs.openjdk.org/browse/JDK-8292933"><span class="s2"><span style="font-size:10.0pt;text-decoration:none">JDK-8292933</span></span></a></span></span>
 Multiple focused components accepting keyboard input<o:p></o:p></li></ul>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New"">I was thinking we could have a FocusManager that would keep track of where the focus is at any given time (across all the visible Stages), as well as FocusTraversalPolicy that governs
 traversal on a Stage or a Parent.  The FocusManager would expose a currentFocusOwner and a currentFocusedStage properies, provide programmatic focus traversal, manage the keys etc.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New"">I also think Swing got the focus subsystem right, so perhaps we could consider doing something similar.  Would this change be backward compatible, or it will introduce breaking changes
 in the public APIs?<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New"">-andy<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New""><o:p> </o:p></span></p>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal" style="margin-bottom:12.0pt"><b><span style="font-size:12.0pt;color:black">From:
</span></b><span style="font-size:12.0pt;color:black">openjfx-dev <openjfx-dev-retn@openjdk.org> on behalf of Chuck Davis <cjgunzel@gmail.com><br>
<b>Date: </b>Tuesday, May 16, 2023 at 05:53<br>
<b>To: </b><br>
<b>Cc: </b>openjfx-dev <openjfx-dev@openjdk.org><br>
<b>Subject: </b>Re: Improvements for Focus Traversal code<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">One of the things I really miss about Swing was the ease with which we could move focus programmatically.  All we had to do was call the focus object (don't remember the name) and call focus.next() or focus.previous(). 
 Having to get the next Control and call Control.requestFocus() is a hack.  While the focus traversal code is being upgraded, please include Control.getFocusTraversal().next() and Control.getFocusTraversal().previous() so we can catch up with Swing capabilities. 
 Those of us old enough to have grown up with real computers still remember that focus from input to input is supposed to be done by pressing the "enter" key -- NOT the "tab" key.<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">On Tue, May 16, 2023 at 4:55 AM John Hendrikx <<a href="mailto:john.hendrikx@gmail.com">john.hendrikx@gmail.com</a>> wrote:<o:p></o:p></span></p>
</div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in">
<p class="MsoNormal" style="margin-bottom:12.0pt"><span style="font-size:11.0pt">Hi list,<br>
<br>
I've gone down another rabbit hole in JavaFX, this time related to focus <br>
traversal.<br>
<br>
# Navigation keys are not handled universally for all controls<br>
<br>
Some controls install custom behaviors, and some don't.  The custom <br>
behaviors often include direct handling of navigation keys <br>
(getFocusTraversalMappings).  The controls that don't (often controls <br>
that are not focus traversable by default, like Label) rely on the <br>
SceneEventDispatcher to handle navigation keys.<br>
<br>
However, this leads to subtle differences; when placed inside another <br>
control that may be interested in the navigation keys (like ListView, <br>
TableView, ScrollPane) a Button will still respond to all navigation <br>
keys directly (and correctly), while a focus traversable Label will let <br>
these events bubble up, possibly to be consumed by its parent (ie. <br>
pressing DOWN may not focus another control inside the View, but instead <br>
scroll the view down as if the View had focus).  This is inconsistent.<br>
<br>
==> As any Node can be made focus traversable, I think the handling of <br>
navigation keys should be done by Node itself; basically, after all <br>
event handlers have run for a Node, a final event handler should be <br>
called which checks for unconsumed navigation key events, and triggers <br>
navigation only then.  This would make all Nodes work consistently where <br>
navigation is concerned and would remove the need to add focus traversal <br>
key mappings in Behaviors.  Button would respond as it always has, while <br>
a focus traversable label would now work exactly as a Button would, even <br>
when nested in a View type parent.<br>
<br>
# Translate Navigation Keys to Higher Level Events<br>
<br>
When a key is determined to trigger navigation, we should translate this <br>
to a new type of event, for example NavigationEvent (or TraversalEvent). <br>
This Key event that triggered it is consumed, and this new event is <br>
fired.  This new event captures the intention to navigate somewhere <br>
(Navigate NEXT, PREVIOUS, UP, DOWN, LEFT, RIGHT) and participates in the <br>
usual filtering/bubbling phases.  This is far better than having a <br>
(potentially platform specific) key event with multiple possible <br>
meanings (sometimes it navigates, sometimes it scrolls) when one wants <br>
to deal with navigation issues.<br>
<br>
This would solve a number of problems:<br>
<br>
- Navigation events can all be handled in the same place, the Scene.<br>
- One can trigger navigation in a nice programmatic way, instead of <br>
simulating a key press, which may be platform specific, one can send out <br>
a NavigationEvent#NEXT event type.<br>
- Influencing the focus traversal mechanism is much easier, as these <br>
events can be listened to, filtered and consumed as needed. Contrast <br>
this with trying to do this with key events which may have different <br>
meanings depending on the state of the control receiving them.  Blocking <br>
navigation for example is a matter of consuming a type of Navigation <br>
event before it bubbles up to the Scene.<br>
- It could allow for focus traversal that goes beyond Scenes (ie. focus <br>
another Scene, or a Swing control).  Navigation events not consumed by <br>
Scene could trigger other actions.  For NEXT/PREVIOUS navigation this <br>
may require a Scene setting that prevents wrapping around to the <br>
first/last control, and perhaps with the help of some further Navigation <br>
event variations (like nagivating to FIRST or LAST).<br>
- A lot of the Accessor code to be able to reach the (private) traverse <br>
methods would not be needed anymore as the event system can reach the <br>
Scene code without needing accessors<br>
<br>
--John<br>
<br>
<br>
<o:p></o:p></span></p>
</blockquote>
</div>
</div>
</body>
</html>