<Swing Dev> A proposal for a behavior change about mnemonic key
Pavel Porvatov
pavel.porvatov at oracle.com
Fri Jan 20 11:37:03 UTC 2012
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 <mailto: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 <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
>>
>
>
>
>
> --
> Best Regards,
> Sean Chou
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/swing-dev/attachments/20120120/2ac5c9c0/attachment.html>
More information about the swing-dev
mailing list