Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6493715

Mnemonic character appears in text component

    Details

    • Subcomponent:
    • Understanding:
      Cause Known
    • CPU:
      x86
    • OS:
      linux

      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;
              }
          }

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                ant Anton Tarasov
                Reporter:
                tyao Ting-Yun Ingrid Yao (Inactive)
              • Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Imported:
                  Indexed: