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

Bug in the getKeyChar method of the AccessBridge class

XMLWordPrintable

      Note: This bug occurs with e.g. Java VM 17 and 21 running on Windows, it does not occur on macOS.

      Issue: If a JMenuItem contains a shortcut like “Ctrl + Comma”, the private method getKeyChar of the AccessBridge class cuts the “Comma” text to the first character and hence transfers “C” (instead of “Comma”) via the AccessBridge API. For a shortcut “Ctrl + Comma” in a menu item, screen readers announce “Ctrl + C” instead of “Ctrl + Comma” as shortcut, and the user may use a wrong shortcut for this menu action.

      For a shortcut like “Ctrl + Period” this method cuts the “Period” to “P”, the AccessBridge API sends “P” as char and hence a screen reader announces “Ctrl + P” as shortcut.
      For a shortcut like “Ctrl + Enter” this method cuts the “Enter” to “E”, the AccessBridge API sends “E” as char and hence a screen reader announces “Ctrl + E” as shortcut.

      You can use the simple class Test_JMenuItem_KeyStrokes below for testing the java application on Windows with a screen reader, or with the jaccessinspector.

      Following code in the method getKeyChar of the AccessBridge (starting with line 3970) is the cause for this issue:

      String keyText = KeyEvent.getKeyText(keyStroke.getKeyCode());
      debugString("[INFO]: Shortcut is: " + keyText);
      if (keyText != null || keyText.length() > 0) {
      CharSequence seq = keyText.subSequence(0, 1);
      if (seq != null || seq.length() > 0) {
      return seq.charAt(0);
      }
      }

      When keyText is for example “Comma”, seq.charAt(0) = C, and then method will return “C” instead of Comma.


      public class Test_JMenuItem_KeyStrokes
      {

          public static void main(String[] args)
          {
              JMenuBar menuBar = new JMenuBar();
              JMenu menu = new JMenu("Menu with Keystrokes");
              menu.setMnemonic(KeyEvent.VK_M);
              menuBar.add(menu);

              KeyStroke keyStroke1 = KeyStroke.getKeyStroke(KeyEvent.VK_COMMA, InputEvent.CTRL_DOWN_MASK);
              KeyStroke keyStroke2 = KeyStroke.getKeyStroke(KeyEvent.VK_COMMA, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK);
              KeyStroke keyStroke3 = KeyStroke.getKeyStroke(KeyEvent.VK_COMMA, InputEvent.CTRL_DOWN_MASK | InputEvent.ALT_DOWN_MASK);
              KeyStroke keyStroke4 = KeyStroke.getKeyStroke(KeyEvent.VK_PERIOD, InputEvent.CTRL_DOWN_MASK);
              KeyStroke keyStroke5 = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK);

              JCheckBoxMenuItem menuItem1 = new JCheckBoxMenuItem("First Menu Item");
              menuItem1.setAccelerator(keyStroke1);
              JCheckBoxMenuItem menuItem2 = new JCheckBoxMenuItem("Second Menu Item");
              menuItem2.setAccelerator(keyStroke2);
              JCheckBoxMenuItem menuItem3 = new JCheckBoxMenuItem("Third Menu Item");
              menuItem3.setAccelerator(keyStroke3);
              JCheckBoxMenuItem menuItem4 = new JCheckBoxMenuItem("Fourth Menu Item");
              menuItem4.setAccelerator(keyStroke4);
              JCheckBoxMenuItem menuItem5 = new JCheckBoxMenuItem("Fifth Menu Item");
              menuItem5.setAccelerator(keyStroke5);

              menu.add(menuItem1);
              menu.add(menuItem2);
              menu.add(menuItem3);
              menu.add(menuItem4);
              menu.add(menuItem5);

              JFrame frame = new JFrame("A Frame with Menu");
              frame.add(new JCheckBox("A checkbox"));
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              frame.setJMenuBar(menuBar);
              frame.setSize(300, 200);
              frame.setVisible(true);
          }
      }

            abhiscxk Abhishek Kumar
            mbaesken Matthias Baesken
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: