JDK-6493715 : Mnemonic character appears in text component
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 6,6u2
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • OS: linux
  • CPU: x86
  • Submitted: 2006-11-14
  • Updated: 2011-04-29
Related Reports
Duplicate :  
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0-rc"
Java(TM) SE Runtime Environment (build 1.6.0-rc-b104)
Java HotSpot(TM) 64-Bit Server VM (build 1.6.0-rc-b104, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Linux muellerp02linux 2.6.11.4-20a-smp #1 SMP Wed Mar 23 21:52:37 UTC 2005 x86_64 x86_64 x86_64 GNU/Linux


EXTRA RELEVANT SYSTEM CONFIGURATION :
This also happens on 32-bit Linux

A DESCRIPTION OF THE PROBLEM :
When a menu item is triggered via a mnemonic the corresponding character ends up appearing in the text component that had focus before the menu was activated.  This only happens when the text component has a heavyweight ancestor other than the frame itself.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Run the attached HeavyMnemonicProblem class on Linux
2. Select the File menu
3. Invoke the Test menu item by pressing its mnemonic 't'.
4. Observe that the character 't' appears in the text area.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No character should appear in the text component as a result of triggering a menu item using its mnemonic
ACTUAL -
The mnemonic character both triggers the menu item and appears in the text component

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class HeavyMnemonicProblem {

    public static void main(String[] args) {

        JPopupMenu.setDefaultLightWeightPopupEnabled(false);
        JFrame frame = new JFrame("Heavyweight/Mnemonic Problem");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Add a heavyweight panel containing a lightweigth MJTextArea to the frame's
        // content pane.
        Panel heavyPanel   = new Panel(new BorderLayout());
        JTextArea textArea = new JTextArea();
        heavyPanel.add(textArea, BorderLayout.CENTER);
        frame.getContentPane().add(heavyPanel);

        // Add a menu bar with a mnemonic
        JMenuBar bar = new JMenuBar();
        JMenu    menu = new JMenu("File");
        menu.setMnemonic('F');
        JMenuItem item = new JMenuItem("Test");
        item.setMnemonic('T');
        item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                System.out.println("Test");
            }
        });
        menu.add(item);
        bar.add(menu);
        frame.setJMenuBar(bar);

        // Add an AWTEventListener for diagnostics
        AWTEventListener awtListener = new AWTEventListener() {
            public void eventDispatched(AWTEvent event) {
                System.out.print(event.paramString());
                System.out.println(" on " + event.getSource().getClass().getName());
            }
        };
        Toolkit.getDefaultToolkit().addAWTEventListener(awtListener, AWTEvent.KEY_EVENT_MASK);

        frame.setBounds(100, 100, 400, 300);
        frame.setVisible(true);
    }
 }

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

CUSTOMER SUBMITTED WORKAROUND :
The problem can be prevented by using a KeyEventDispatcher to detect and discard key typed events for a component other than the root pane when the preceeding key pressed event was on the root pane.  The following code does this:

    KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new StrayKeyTypedSuppressor());

   static class StrayKeyTypedSuppressor implements KeyEventDispatcher
    {
        private Component sPressedComponent;

        public boolean dispatchKeyEvent(KeyEvent event) {
            if (event.getID() == KeyEvent.KEY_PRESSED) {
                if (event.getComponent() instanceof JRootPane)
                    sPressedComponent = event.getComponent();
            } else {
                if (event.getID() == KeyEvent.KEY_TYPED &&
                    sPressedComponent != null && sPressedComponent != event.getComponent())
                    return true;
                sPressedComponent = null;
            }
            return false;
        }
    }

Comments
EVALUATION The cause of the problem is that in XAWT we send all focus-related events using PeerEvent with ultimate priority (XWindow.sendEvent()). Unfortunately (for Swing) we can not chamge this since some our reg tests fail after that (it looks like we rely on this order). Do not know when/if we will be able to fix this :(
16-01-2007

EVALUATION it is reproducible with 1.5 (XToolkit) but not with MToolkit)
22-11-2006

EVALUATION easily reproducible on linux :(
22-11-2006

EVALUATION Looks like an old problem AWT fought with Reassigned to AWT team
21-11-2006

EVALUATION It looks like a duplicate of 6391688, 6396785, 6363026 and so on. I cannot reproduce the bug under Windows XP on *ustang b95 and current *olphin. Maybe it is Linux related problem?
17-11-2006