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

Sean Chou zhouyx at linux.vnet.ibm.com
Wed Feb 22 08:00:47 UTC 2012


Hi Pavel,

     The current behavior correspondent to Windows' behavior . However, the
modification is in javax.swing.KeyboardManager , it is LAF independent I
think.
I uploaded a webrev about the modification :
http://cr.openjdk.java.net/~zhouyx/7108342/webrev.00/  .  Please have a
look.


On Fri, Jan 20, 2012 at 7:37 PM, Pavel Porvatov
<pavel.porvatov at oracle.com>wrote:

>  Hi Sean,
>
> Hi Pavel,
>
>  About the LAF, I didn't quite get you. Do you mean we should ask users to
> press "esc" before next mnemonic key event takes effect when using gtk LAF?
> Or, do you mean we should implement the focus transfer code in each LAF?
>
> Previously, I thought this patch is just a small enhancement to current
> implementation and the enhancement benefits all LAFs.
>
> I meant that native look and feels (like Windows and GTK LAFs) should have
> behavior of native system. As I wrote there are a couple differences
> between these LAFs:
> ----------------
>
> 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
> ----------------
>
> As I understand your current implementation correspondent to WindowsLAF,
> right? We can add the new functionality in cross platform look and feel, so
> we could use your patch for Metal and Nimbus as well. But Motif and GTK
> should use different strategy. I'd suggest to use your new behavior only
> for Windows, Nimbus and Metal, but doesn't touch Motif and GTK .
>
> Regards, Pavel
>
>
>
> On Thu, Nov 24, 2011 at 1:57 AM, Pavel Porvatov <pavel.porvatov at oracle.com
> > wrote:
>
>>  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
>> > 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>
>>>
>>>>  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
>>>>
>>>>  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>
>>>>
>>>>  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>
>>>>
>>>>  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>
>>>>
>>>>  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>
>>>>
>>>>  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> wrote:
>>>>
>>>>  Hi,
>>>>
>>>>     Is there anybody interested in this feature? Or any other
>>>> comments?
>>>>
>>>> 2011/4/21 Sean Chou <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>
>>>>
>>>> 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
>>
>>
>>
>
>
>  --
> 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/20120222/f06eb4d4/attachment.html>


More information about the swing-dev mailing list