<Swing Dev> A proposal for a behavior change about mnemonic key

Pavel Porvatov pavel.porvatov at oracle.com
Wed Nov 23 17:57:16 UTC 2011


Hi Sean,

We still doesn't have consensus about native LAF behavior. As noticed 
Mario "I believe that native look and feel should mandate the different 
  keybindings". I agree with him and I'd like to not extend the new 
behavior on all LAFs.

I also glanced at the fix and have one comment: you should use 
getModifiersEx method instead of getModifiers (see javadoc for the 
InputEvent#ALT_MASK field for details)

Regards, Pavel
> Hi all,
>
>     I modified the patch and added the testcase, please see attachment.
>
>     However, the testcase works on windows, but does not work right on 
> linux. That's
> the reason for the Manualbug7108342.java file. When I test it 
> manually, it works. And
> because of this problem, I haven't tested it with jtreg.
>
>     Following is the scenario of testcase:
>     The test has three buttons with Mnemonic key "b", at start up, 
> focus is on button1,
> when alt+b is pressed, focus goes to button3, and if pressed again, it 
> goes to button2,
> and then button1, etc.
>
>     When the testcase runs on linux, only button3 and button1 get 
> focused, and there
> are 18 focus events recorded instead of 9. I'm not sure what's the 
> problem with it.
> When I press alt+b manually(using Manualbug7108342.java), it works well.
>
>     Does anyone have some comments about the patch or the testcase ?
>
> On Sat, Oct 8, 2011 at 7:35 PM, Pavel Porvatov 
> <pavel.porvatov at oracle.com <mailto:pavel.porvatov at oracle.com>> wrote:
>
>     Hi Sean,
>>     Hi Pavel,
>>
>>        Your observation is right, but I can't agree with the
>>     conclusion. Windows and
>>     GTK behave differently about how to close an opened menu. Under
>>     GTK, press
>>     "alt" can not close an opened menu, so, the "esc" is used to
>>     close it; while
>>     windows performs more friendly, when mnemonic key is pressed
>>     again, the first
>>     opened menu is closed automatically. This is totally about how to
>>     close an
>>     opened menu, and it doesn't change the fact that menus with same
>>     mnemonic
>>     key are iterated.
>>
>>        On the other side, swing implementation doesn't follow GTK's
>>     behavior about
>>     how to close the menu at all. Open the swingset2 and you can find
>>     its behavior
>>     is the same with windows. Press "alt+f" and then press "alt+l"
>>     will open the
>>     "look and feel" menu instead of GTK's "alt+f", "esc", and "alt+l".
>>
>>        So, I think GTK's behavior about "use esc to close an opened
>>     menu" is not
>>     user friendly and we can ignore it, while GTK's "iterate over
>>     menus with same
>>     mnemonic key" is better than current java implementation and we
>>     can add
>>     this feature. And if a user wants to use GTK's key sequence
>>     "alt+f", "esc",
>>     "alt+l", it is also functional.
>>
>>        So I think this enhancement will help keep the behavior same
>>     with both these
>>     platforms, how do you think?
>     Sounds reasonable and I don't object now to the decision. Does
>     anybody have ideas (e.g. objections) about the new functionality?
>
>     I glanced at your patch and have the following comments:
>     1. Could you please file CR about the problem
>     2. A test is needed (I think it's possible to write an automatic one)
>     3. Could you please correct the new code to obey our code
>     standards (aligning, spacing, mandatory braces in if/else
>     conditions and others)
>
>     If possible send patch as a webrev, please.
>
>     Thanks, Pavel
>
>
>>
>>     2011/9/21 Pavel Porvatov <pavel.porvatov at oracle.com
>>     <mailto:pavel.porvatov at oracle.com>>
>>
>>         Hi Sean,
>>
>>         I found out that Windows and GTK works in different ways (I
>>         used your apps):
>>
>>         1. When Alt+i is pressed several times:
>>         In Windows focus moves between items
>>         In Ubuntu focus stays at the initially selected item
>>
>>         2. When sequence Alt+i and Escape pressed several times
>>         In Windows the first menu item is selected
>>         In Ubuntu after every sequence the next item is selected
>>
>>         In such case we should use different strategies for different
>>         platforms...
>>
>>
>>         Regards, Pavel
>>
>>>         Hi Pavel,
>>>
>>>             I just tested linux gtk platform.  With gtk2+, ubuntu
>>>         linux with kernel 2.6.38, xfce, x86_32.
>>>         I set four menus with mnemonic "i". Press "alt+i" will
>>>         travel through four menus. The difference
>>>         is that each menu must be closed with "esc" before "alt+i"
>>>         opens the next one.
>>>
>>>             So press "alt+i" opens "File", and press "esc" to close it;
>>>             then press "alt+i" opens "Edit", and press "esc" to
>>>         close it;
>>>             ... for next menu with mnemonic "i"
>>>
>>>         I attached the test application and its ui file. If it is
>>>         blocked, please use
>>>         this link:
>>>         https://docs.google.com/leaf?id=0B8kRxsymP7imOGU1NjhiM2ItMGQ5Ni00NWNhLWJmMDQtZjZiZmQzN2U4ZGUw&hl=en_US
>>>         <https://docs.google.com/leaf?id=0B8kRxsymP7imOGU1NjhiM2ItMGQ5Ni00NWNhLWJmMDQtZjZiZmQzN2U4ZGUw&hl=en_US>
>>>
>>>         Ubuntu x86_32 should work.
>>>
>>>
>>>         So, I think both windows and linux gtk have supported
>>>         traversal of same mnemonic keyed
>>>         items already.
>>>
>>>
>>>         2011/9/14 Pavel Porvatov <pavel.porvatov at oracle.com
>>>         <mailto:pavel.porvatov at oracle.com>>
>>>
>>>             Hi Sean,
>>>>             Hi Pavel,
>>>>
>>>>                 Let's see if this time works. The attachement just
>>>>             contains the exe file written by C#, the application is
>>>>             very simple, I just drag a menu to the default WinForm
>>>>             in VS2003.
>>>>                 Please change the extension from exe1 to exe after
>>>>             unzip as gmail doesn't allow exe file to be sent.
>>>             Yes, I see. And what about other platforms/lafs? Your
>>>             patch affects behavior of all lafs. So we must be sure,
>>>             that such behavior is correct for every supported
>>>             platform...
>>>
>>>             Regards, Pavel
>>>
>>>>
>>>>             2011/9/13 Pavel Porvatov <pavel.porvatov at oracle.com
>>>>             <mailto:pavel.porvatov at oracle.com>>
>>>>
>>>>                 Hi Sean,
>>>>
>>>>                 I think the attached sample was removed because I
>>>>                 didn't get any attachments...
>>>>
>>>>                 Regards, Pavel
>>>>
>>>>>                 Hi Pavel,
>>>>>
>>>>>                    I found C# Form application treats Mnemonics in
>>>>>                 menu in this way. I attached the sample
>>>>>                 application. Press alt+i will iterate over three menu.
>>>>>
>>>>>                 2011/9/13 Pavel Porvatov
>>>>>                 <pavel.porvatov at oracle.com
>>>>>                 <mailto:pavel.porvatov at oracle.com>>
>>>>>
>>>>>                     Hi Sean,
>>>>>>                     Hi,
>>>>>>
>>>>>>                        Thanks.
>>>>>>
>>>>>>                        So is there any one can give me a
>>>>>>                     suggestion about what shall I
>>>>>>                     do if we want these feature ?  Thanks again.
>>>>>                     First of all you should file a bug (RFE
>>>>>                     actually). BTW: before reviewing the fix I'd
>>>>>                     like to ask about OS behavior when there are
>>>>>                     several components with the same mnemonic. How
>>>>>                     Windows XP/Vista/7 and Linux (Gnome/KDE)
>>>>>                     manage the described situation?
>>>>>
>>>>>                     Regards, Pavel
>>>>>
>>>>>
>>>>>>
>>>>>>                     2011/7/6 Jean-Remi Desjardins
>>>>>>                     <jeanremi.desjardins at gmail.com
>>>>>>                     <mailto:jeanremi.desjardins at gmail.com>>
>>>>>>
>>>>>>                         I think that sounds like a great idea!
>>>>>>
>>>>>>                         Regards,
>>>>>>                         Jean-Rémi Desjardins
>>>>>>
>>>>>>                         Sent from my iPhone (so don't expect me
>>>>>>                         to be too verbose)
>>>>>>
>>>>>>                         On 2011-07-06, at 5:42 AM, Sean Chou
>>>>>>                         <zhouyx at linux.vnet.ibm.com
>>>>>>                         <mailto:zhouyx at linux.vnet.ibm.com>> wrote:
>>>>>>
>>>>>>>                         Hi,
>>>>>>>
>>>>>>>                            Is there anybody interested in this
>>>>>>>                         feature? Or any other comments?
>>>>>>>
>>>>>>>                         2011/4/21 Sean Chou
>>>>>>>                         <zhouyx at linux.vnet.ibm.com
>>>>>>>                         <mailto:zhouyx at linux.vnet.ibm.com>>
>>>>>>>
>>>>>>>                             Hi,
>>>>>>>
>>>>>>>                                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.
>>>>>>>
>>>>>>>
>>>>>>>                             The patch is as follows:
>>>>>>>
>>>>>>>                             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
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>                             2011/4/1 Sean Chou
>>>>>>>                             <zhouyx at linux.vnet.ibm.com
>>>>>>>                             <mailto:zhouyx at linux.vnet.ibm.com>>
>>>>>>>
>>>>>>>                                 Hi all,
>>>>>>>
>>>>>>>                                    In daily use, we may
>>>>>>>                                 encounter a problem of mnemonic
>>>>>>>                                 key: there may be several
>>>>>>>                                 controls want the same key to be
>>>>>>>                                 set as mnemonic key. It is not
>>>>>>>                                 common but it does exist.
>>>>>>>
>>>>>>>                                    Current openjdk
>>>>>>>                                 implementation allows users to
>>>>>>>                                 set a same mnemonic key for
>>>>>>>                                 different controls; but during
>>>>>>>                                 the execution, when the mnemonic
>>>>>>>                                 key is pressed,
>>>>>>>                                 the last control always gets the
>>>>>>>                                 action. Users are not able to
>>>>>>>                                 touch other controls with
>>>>>>>                                 that mnemonic key. This may
>>>>>>>                                 confuse them.
>>>>>>>
>>>>>>>                                    If all the controls with the
>>>>>>>                                 same mnemonic key can be
>>>>>>>                                 accessed through, for
>>>>>>>                                 example, when the mnemonic key
>>>>>>>                                 is pressed, the focus is moved
>>>>>>>                                 to the last control,
>>>>>>>                                 and when the mnemonic key is
>>>>>>>                                 pressed again, the focus is
>>>>>>>                                 moved to the second control
>>>>>>>                                 with that mnemonic, it will give
>>>>>>>                                 user the choice to select other
>>>>>>>                                 controls.
>>>>>>>
>>>>>>>                                    Here is an example for the case:
>>>>>>>
>>>>>>>                                 package test;
>>>>>>>
>>>>>>>                                 import java.awt.BorderLayout;
>>>>>>>                                 import java.awt.Container;
>>>>>>>                                 import javax.swing.ButtonGroup;
>>>>>>>                                 import javax.swing.JFrame;
>>>>>>>                                 import javax.swing.JRadioButton;
>>>>>>>
>>>>>>>                                 public class TestFocus extends
>>>>>>>                                 JFrame {
>>>>>>>                                 public TestFocus() {
>>>>>>>                                 Container pane = getContentPane();
>>>>>>>                                 pane.setLayout(new BorderLayout());
>>>>>>>                                 JRadioButton btn1,btn2,btn3;
>>>>>>>                                 btn1 = new JRadioButton("Yes");
>>>>>>>                                 btn1.setMnemonic('Y');
>>>>>>>                                 btn2 = new JRadioButton("Yup");
>>>>>>>                                 btn2.setMnemonic('Y');
>>>>>>>                                 btn3 = new JRadioButton("No");
>>>>>>>                                 btn3.setMnemonic('N');
>>>>>>>                                 btn3.setSelected(true);
>>>>>>>                                 ButtonGroup group = new
>>>>>>>                                 ButtonGroup();
>>>>>>>                                 group.add(btn1);
>>>>>>>                                 group.add(btn2);
>>>>>>>                                 group.add(btn3);
>>>>>>>                                 pane.add(btn1,BorderLayout.NORTH);
>>>>>>>                                 pane.add(btn2,BorderLayout.CENTER);
>>>>>>>                                 pane.add(btn3,BorderLayout.SOUTH);
>>>>>>>                                 setSize(200,200);
>>>>>>>                                 setVisible(true);
>>>>>>>                                 setDefaultCloseOperation(EXIT_ON_CLOSE);
>>>>>>>                                 }
>>>>>>>                                 public static void main(String[]
>>>>>>>                                 args) {
>>>>>>>                                 new TestFocus();
>>>>>>>                                 }
>>>>>>>                                 }
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>                                 -- 
>>>>>>>                                 Best Regards,
>>>>>>>                                 Sean Chou
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>                             -- 
>>>>>>>                             Best Regards,
>>>>>>>                             Sean Chou
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>                         -- 
>>>>>>>                         Best Regards,
>>>>>>>                         Sean Chou
>>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>                     -- 
>>>>>>                     Best Regards,
>>>>>>                     Sean Chou
>>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>                 -- 
>>>>>                 Best Regards,
>>>>>                 Sean Chou
>>>>>
>>>>
>>>>
>>>>
>>>>
>>>>             -- 
>>>>             Best Regards,
>>>>             Sean Chou
>>>>
>>>
>>>
>>>
>>>
>>>         -- 
>>>         Best Regards,
>>>         Sean Chou
>>>
>>
>>
>>
>>
>>     -- 
>>     Best Regards,
>>     Sean Chou
>>
>
>
>
>
> -- 
> Best Regards,
> Sean Chou
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/swing-dev/attachments/20111123/240f9a80/attachment.html>


More information about the swing-dev mailing list