Hi,                                                           

                                                          
                                                          
   Is                                                           there anybody                                                           interested in                                                           this feature?                                                           Or any other                                                           comments? 
                                                          
                                                          
2011/4/21                                                           Sean Chou <zhouyx@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@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">

(original) (raw)

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@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@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

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@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@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@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@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@linux.vnet.ibm.com>

wrote:





Hi,



Is
there anybody
interested in
this feature?
Or any other
comments?



2011/4/21
Sean Chou <zhouyx@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@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