JDK-6888161 : Conflicting item mnemonics post sibling menu rather than cycle (Java & GTK L&Fs)
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 6u15
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: linux_ubuntu
  • CPU: x86
  • Submitted: 2009-10-05
  • Updated: 2011-02-16
  • Resolved: 2009-11-16
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
Reproducible using latest versions of JDK 5, 6, 7. Mainly tested with 6u15.

ADDITIONAL OS VERSION INFORMATION :
2.6.28-15-generic #49-Ubuntu SMP Tue Aug 18 18:40:08 UTC 2009 i686 GNU/Linux


A DESCRIPTION OF THE PROBLEM :
In Java ("Ocean") and GTK L&Fs, if a menu has several items sharing the same mnemonic and another menu also uses that mnemonic, with the first menu posted using Alt-<letter>, pressing the (unmodified) mnemonic letter posts the second menu rather than cycling between the menu items.

Initially observed in NetBeans IDE. In the standard "Java SE" configuration, the Tools menu contains an item "_D_TDs and XML Schemas"; Alt-T D works as expected. If you add the "Module Manager" module from the experimental update center, which adds a "Mo_d_ule Manager" menu item to the Tools menu, Alt-T D posts the "_D_ebug" menu rather than cycling between the two items in the Tools menu.

There are numerous issues in the bug database relating to mnemonics and mnemonic conflicts, but all are marked resolved, and I could not find anything exactly matching this issue.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached program, with the call to UIManager.setLookAndFeel left in or commented out.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Typing Alt-A, Alt-B, Alt-C should post the corresponding menu. With A posted, typing B should activate its menu item, and typing any other letter should have no effect. With B posted, typing A should cycle between the two menu items (with Enter to activate), and no other letters should matter. With C posted, D should cycle, and again other letters should do nothing.
ACTUAL -
The program behaves as expected when run on Win XP using native L&F.

On Ubuntu using Java L&F, or Ubuntu using GTK L&F, or Win XP using Java L&F, there are two issues:

1. Typing an unmodified letter which corresponds to the mnemonic of another menu posts that menu unless there is one item with that mnemonic in the current menu. For example, with A posted, typing B selects A > B as expected but typing C causes the C menu to be posted instead of A, rather than simply being ignored. In and of itself this is harmless, if odd and useless since you could just use ESC Alt-C or arrow keys in the unlikely event you wanted to switch to a different menu. (I cannot observe this behavior in a native Gnome/GTK application, so I must conclude that it is not the result of intentional mimicry of some Unix convention.)

2. With C posted, typing D cycles between the two menu items as expected. But with B posted, typing A posts the A menu *instead of* cycling between the two menu items. In other words, the odd behavior in issue #1 is taking precedence over the normal behavior of cycling when there is a mnemonic conflict.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.UIManager;
public class Main extends JFrame {
    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception x) {
                    x.printStackTrace();
                }
                new Main().setVisible(true);
            }
        });
    }
    public Main() {
        initComponents();
    }
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {

        menubar = new javax.swing.JMenuBar();
        a = new javax.swing.JMenu();
        ab = new javax.swing.JMenuItem();
        b = new javax.swing.JMenu();
        ba1 = new javax.swing.JMenuItem();
        ba2 = new javax.swing.JMenuItem();
        c = new javax.swing.JMenu();
        cd1 = new javax.swing.JMenuItem();
        cd2 = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        getContentPane().setLayout(null);

        a.setMnemonic('A');
        a.setText("A");

        ab.setMnemonic('B');
        ab.setText("B");
        ab.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                abActionPerformed(evt);
            }
        });
        a.add(ab);

        menubar.add(a);

        b.setMnemonic('B');
        b.setText("B");

        ba1.setMnemonic('A');
        ba1.setText("A1");
        ba1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ba1ActionPerformed(evt);
            }
        });
        b.add(ba1);

        ba2.setMnemonic('A');
        ba2.setText("A2");
        ba2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                ba2ActionPerformed(evt);
            }
        });
        b.add(ba2);

        menubar.add(b);

        c.setMnemonic('C');
        c.setText("C");

        cd1.setMnemonic('D');
        cd1.setText("D1");
        cd1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cd1ActionPerformed(evt);
            }
        });
        c.add(cd1);

        cd2.setMnemonic('D');
        cd2.setText("D2");
        cd2.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cd2ActionPerformed(evt);
            }
        });
        c.add(cd2);

        menubar.add(c);

        setJMenuBar(menubar);

        pack();
    }// </editor-fold>
    private void abActionPerformed(java.awt.event.ActionEvent evt) {
        System.out.println("A > B");
    }
    private void ba1ActionPerformed(java.awt.event.ActionEvent evt) {
        System.out.println("B > A1");
    }
    private void ba2ActionPerformed(java.awt.event.ActionEvent evt) {
        System.out.println("B > A2");
    }
    private void cd1ActionPerformed(java.awt.event.ActionEvent evt) {
        System.out.println("C > D1");
    }
    private void cd2ActionPerformed(java.awt.event.ActionEvent evt) {
        System.out.println("C > D2");
    }
    // Variables declaration - do not modify
    private javax.swing.JMenu a;
    private javax.swing.JMenuItem ab;
    private javax.swing.JMenu b;
    private javax.swing.JMenuItem ba1;
    private javax.swing.JMenuItem ba2;
    private javax.swing.JMenu c;
    private javax.swing.JMenuItem cd1;
    private javax.swing.JMenuItem cd2;
    private javax.swing.JMenuBar menubar;
    // End of variables declaration
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
None known.

Comments
EVALUATION This has been fixed recently under bug id 6827786.
16-11-2009