<div>Hi,</div><div><br></div><div>   I have a simple patch to demo the new behavior. With the patch, the focus will go through the radiobuttons with mnemonic key Y when alt+y is pressed instead of select the last.</div><div>
<br></div><div><br></div><div>The patch is as follows:</div><div><pre>diff -r 554adcfb615e src/share/classes/javax/swing/KeyboardManager.java
--- a/src/share/classes/javax/swing/KeyboardManager.java        Wed Mar 16 15:01:07 2011 -0700
+++ b/src/share/classes/javax/swing/KeyboardManager.java        Thu Mar 17 14:57:14 2011 +0800
@@ -251,6 +251,93 @@
                  }
              } else if ( tmp instanceof Vector) { //more than one comp registered for this
                  Vector v = (Vector)tmp;
+                 
+                 /* The below code is added to make sure the focus is not always 
+                    transferred to the last component in the vector when         
+                    more than one component have the same mnemonic              
+                 */
+                     if ((e.getModifiers() & Event.ALT_MASK) == Event.ALT_MASK) {
+                      /* Mnemonic key should transfer the focus only, do not select.
+                       * The following code works in this way:
+                       * 1. If only one component in the vector is visible, fireBinding on it.
+                       * 2. If multi-components in the vector are visible, move the focus to next component.
+                       *    2.1 If the next component is not a JAbstractButton, fireBinding on it.
+                       *    2.2 If the next component is a JMenu, which is a JAbstractButton, fireBinding 
+                       *        on it to open the menu.
+                       *    2.3 If the next component is another JAbstractButton like JRadioButton. Request
+                       *        focus on it instead of fireBinding. To AVOID SELECTION & CLICK of the button.
+                       * 3. If the code is triggered by release event, fireBinding on current focus component
+                       *    instead of move focus.
+                       * 4. Further consideration: there may be more swing control like JMenu, or customized
+                       *    controls, which may break this behavior.
+                       */
+                      // This has alt as it's modifier so this could be a mnemonic
+                      Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); 
+                      {
+                      // If only one visible component, invoke it. 
+                      int visibleComponentCounter = 0;
+                      int nextFocus = 0;
+                      for (int i =  0; i < v.size(); i++){
+                          JComponent c = (JComponent) v.elementAt(i);
+                          if (c.isShowing() && c.isEnabled()){
+                                visibleComponentCounter++ ;
+                                     nextFocus = i;
+                            }
+                      }
+                      if (visibleComponentCounter == 1){
+                            JComponent tmpc = (JComponent) v.elementAt(nextFocus);
+                            fireBinding(tmpc, ks, e, pressed);
+                          if (e.isConsumed())
+                                 return true;
+                      }
+                      // If multi-components are visible, do not select the button, just move the focus.
+                      for (int counter = v.size() - 1; counter >= 0; counter--) {
+                          JComponent c = (JComponent) v.elementAt(counter);
+                          if (c.isShowing() && c.isEnabled()) {
+                              if ((c == focusOwner)
+                                       || (c instanceof JLabel && ((JLabel) c).getLabelFor() == focusOwner)) { 
+                                  if (e.getID() == KeyEvent.KEY_RELEASED){
+                                            nextFocus = counter;
+                                            break;
+                                  }
+                                   nextFocus = (counter - 1 + v.size()) % v.size();
+                                  break;
+                              }
+                          }
+                      }
+                      for (; nextFocus >= 0; nextFocus--) {
+                          JComponent c = (JComponent) v.elementAt(nextFocus);
+                          if (c.isShowing() && c.isEnabled()) {
+                              break;
+                          }
+                      }
+                      if (nextFocus >= 0) {
+                          JComponent tmpc = (JComponent) v.elementAt(nextFocus);
+                          // Next is the hack for this accessibility:
+                          // For general Buttons, do not press them, but request focus only.
+                          // For special buttons like JMenu, needs press.
+                          // If it is not a button, let the component handles by itself.
+                          if (!(tmpc instanceof javax.swing.AbstractButton)){
+                                  fireBinding(tmpc, ks, e, pressed);
+                              if (e.isConsumed())
+                                   return true;
+                          }
+                          if (tmpc instanceof JMenu ) {
+                              fireBinding(tmpc, ks, e, pressed);
+                              tmpc.requestFocusInWindow();
+                              if (e.isConsumed())
+                                  return true;
+                          } else {
+                              boolean result = tmpc.requestFocusInWindow();
+                              e.consume();
+                              return result;
+                          }
+                      }
+                      // If it is not handled here, default behavior is selecting the last.
+                      }
+                 }
+                 
+                 
                  // There is no well defined order for WHEN_IN_FOCUSED_WINDOW
                  // bindings, but we give precedence to those bindings just
                  // added. This is done so that JMenus WHEN_IN_FOCUSED_WINDOW
</pre></div><div><br></div><br><br><div class="gmail_quote">2011/4/1 Sean Chou <span dir="ltr"><<a href="mailto:zhouyx@linux.vnet.ibm.com">zhouyx@linux.vnet.ibm.com</a>></span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div>Hi all,</div><div><br></div><div>   In daily use, we may encounter a problem of mnemonic key: there may be several</div><div>controls want the same key to be set as mnemonic key. It is not common but it does exist.</div>

<div><br></div><div>   Current openjdk implementation allows users to set a same mnemonic key for </div><div>different controls; but during the execution, when the mnemonic key is pressed,</div><div>the last control always gets the action. Users are not able to touch other controls with</div>

<div>that mnemonic key. This may confuse them.</div><div><br></div><div>   If all the controls with the same mnemonic key can be accessed through, for</div><div>example, when the mnemonic key is pressed, the focus is moved to the last control, </div>

<div>and when the mnemonic key is pressed again, the focus is moved to the second control</div><div>with that mnemonic, it will give user the choice to select other controls.</div><div><br></div><div>   Here is an example for the case:</div>

<div><br></div><div>package test;</div><div><br></div><div>import java.awt.BorderLayout;</div><div>import java.awt.Container;</div><div>import javax.swing.ButtonGroup;</div><div>import javax.swing.JFrame;</div><div>import javax.swing.JRadioButton;</div>

<div><br></div><div>public class TestFocus extends JFrame {<span style="white-space:pre-wrap">  </span></div><div><span style="white-space:pre-wrap"> </span>public TestFocus() {</div><div>
<span style="white-space:pre-wrap">             </span>Container pane = getContentPane();</div><div><span style="white-space:pre-wrap">               </span>pane.setLayout(new BorderLayout());</div><div><span style="white-space:pre-wrap">              </span>JRadioButton btn1,btn2,btn3;</div>

<div><span style="white-space:pre-wrap">          </span>btn1 = new JRadioButton("Yes");</div><div><span style="white-space:pre-wrap">                </span>btn1.setMnemonic('Y');</div><div>
<span style="white-space:pre-wrap">             </span>btn2 = new JRadioButton("Yup");</div><div><span style="white-space:pre-wrap">                </span>btn2.setMnemonic('Y');</div><div><span style="white-space:pre-wrap">           </span>btn3 = new JRadioButton("No");</div>

<div><span style="white-space:pre-wrap">          </span>btn3.setMnemonic('N');</div><div><span style="white-space:pre-wrap">           </span>btn3.setSelected(true);</div><div><span style="white-space:pre-wrap">          </span>ButtonGroup group = new ButtonGroup();</div>

<div><span style="white-space:pre-wrap">          </span>group.add(btn1);</div><div><span style="white-space:pre-wrap">         </span>group.add(btn2);</div><div><span style="white-space:pre-wrap">         </span>group.add(btn3);</div>
<div><span style="white-space:pre-wrap">          </span>pane.add(btn1,BorderLayout.NORTH);</div><div><span style="white-space:pre-wrap">               </span>pane.add(btn2,BorderLayout.CENTER);</div><div><span style="white-space:pre-wrap">              </span>pane.add(btn3,BorderLayout.SOUTH);</div>

<div><span style="white-space:pre-wrap">          </span>setSize(200,200);</div><div><span style="white-space:pre-wrap">                </span>setVisible(true);</div><div><span style="white-space:pre-wrap">                </span>setDefaultCloseOperation(EXIT_ON_CLOSE);<span style="white-space:pre-wrap">                </span></div>

<div><span style="white-space:pre-wrap">  </span>}</div><div><span style="white-space:pre-wrap">        </span></div><div><span style="white-space:pre-wrap"> </span>public static void main(String[] args) {</div>
<div><span style="white-space:pre-wrap">          </span>new TestFocus();</div><div><span style="white-space:pre-wrap"> </span>}</div><div>}</div><div><br></div><br><div><br></div><div><br>-- <br>
Best Regards,<br>Sean Chou<br><br>
</div>
</blockquote></div><br><br clear="all"><br>-- <br>Best Regards,<br>Sean Chou<br><br>