<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