JDK-8028241 : Java Access Bridge: F key shortcuts not working if Ctrl, Alt, Shift modifier used
  • Type: Bug
  • Component: client-libs
  • Affected Version: 8
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2013-11-12
  • Updated: 2015-01-21
  • Resolved: 2014-07-01
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other JDK 7 JDK 8 JDK 9
2.0.6Fixed 7u76Fixed 8u40Fixed 9 b24Fixed
Related Reports
Relates :  
Relates :  
The code in com.sun.java.accessibility.AccessBridge.getModifiers needs updating to not return as soon as an Fkey is encountered.  Bit 256 (Fkey indicator) needs to be combined with the other modifiers for ctrl, alt, shift).
<SQE> Start JAWS and then run the attached Test.jar. - Press Alt + F. You should hear the first menu item, Alpha, A, Control plus A - Press downarrow. You should hear F1, 1, Control plus F1 - Press downarrow. You should hear Bravo, B, Shift plus Control plus B - Press downarrow. You should hear F2, 2, Shift plus Control plus F2 - Press downarrow. You should hear Charlie, C, Shift plus Control plus Alt plus C - Press downarrow. You should hear F3, 3, Shift plus Control plus Alt plus F3 - Press downarrow. You should hear Del, Shift plus Control plus Delete // See Note 1 Note 1: As of this writing JAWS is at version 15.0.10026 and does not yet have support for control characters such as the Delete key so until that is fixed by Freedom Scientific nothing will be heard. Note 2: Occasionally I have noticed that speech and keyboard operation cease after pressing up/down arrow to move through the menu. This does not happen with NVDA so I assume it's a JAWS problem. I will notify Freedom Scientific once this fix is available in a 9 EA download. </SQE>

JAWS does not distinguish between a mnemonic and an accelerator (shortcut). It speaks them all in the order they are found in the keyBindingInfo member of the AccessibleKeyBindings structure. In the case where there is neither a mnemonic or an accelerator key, set keyBindingsCount to 0. In the case where there is either a mnemonic but no accelerator key or no mnemonic but an accelerator key set keyBindingsCount to 1. In the case where there is both a mnemonic and an accelerator key set keyBindingsCount to 2. In the case where keyBindingsCount is set to 2, it would be best if the mnemonic was first since that is what JAWS users are used to. There is no need to handle the case of an accelerator key but no mnemonic by setting keyBindingsCount to 2 and then using a special value for character to indicate that there is no mnemonic.

Another issue: If a menu item does not have an underlined letter (the mnemonic of the JMenuItem was not specified), the getAccessibleKeyBindings function does not return any information about the accelerator key even if that menu item does have an accelerator key assigned to it. The code assumes that there will always be a mnemonic if there is an accelerator, i.e. the binding count can be 0, 1, or 2 but if it's 1 then that's always a mnemonic. Determine a character code to use to indicate there is no mnemonic, e.g. 0 or -1.

Related: https://bugs.openjdk.java.net/browse/JDK-8012011 https://bug.oraclecorp.com/pls/bug/webbug_edit.edit_info_top?rptno=16355338

JAWS has added support for a bit 9 modifier to handle virtual key modifiers, i.e. modifiers in addition to ctrl, alt, and shift. Bit 9 should be set if a control key is pressed: VK_BACK_SPACE (8), VK_DELETE (127), VK_DOWN (40), VK_END (35), VK_HOME (36), VK_INSERT (155), VK_KP_DOWN (225), VK_KP_LEFT (226), VK_KP_RIGHT (227), VK_KP_UP (224), VK_LEFT (37) VK_PAGE_DOWN (34), VK_PAGE_UP (33), VK_RIGHT (39), VK_UP (38) The virtual keys are defined here: http://docs.oracle.com/javase/7/docs/api/constant-values.html#java.awt.event.KeyEvent.CHAR_UNDEFINED Below is some proposed code. Note that it only shows support for backspace and delete so it needs modification to add support for at least the above mentioned VKs. Also consider if the support for VKs might be generalized to support more VKs than just those listed above, without breaking something else. Just supporting the ones above is sufficient though. // New method private int controlCode(KeyStroke keyStroke) { int code = keyStroke.getKeyCode(); if (code == KeyEvent.VK_BACK_SPACE || code == KeyEvent.VK_DELETE) { return code; } else { return 0; } } // Existing method modified to use above method // See comment starting with *** private int getModifiers(KeyStroke keyStroke) { int modifiers = 0; // Is the accelerator an FKey? int fKey = fKeyNumber(keyStroke); if (fKey != 0) { // 0-3 are shift, ctrl, meta, alt // 4-7 are for Solaris workstations (though not being used) modifiers |= 1 << 8; // This was a return, thus the bug } // *** next five lines are new // Is the accelerator a control character? int keyCode = controlCode(keyStroke); if (keyCode != 0) { modifiers |= 1 << 9; } // The following is needed in order to handle translated modifiers. // getKeyModifiersText doesn't work because for example in German Strg is // returned for Ctrl. // Get the first three letters of the provided KeyStroke. This comes back in en_US. String text = keyStroke.toString().substring(0, 3); // Meta+Ctrl+Alt+Shift if (text.indexOf("met") >= 0) { modifiers |= ActionEvent.META_MASK; } if (text.indexOf("ctr") >= 0) { modifiers |= ActionEvent.CTRL_MASK; } if (text.indexOf("alt") >= 0) { modifiers |= ActionEvent.ALT_MASK; } if (text.indexOf("shi") >= 0) { modifiers |= ActionEvent.SHIFT_MASK; } debugString("getModifiers: text = "+text+"; modifiers = "+modifiers); return modifiers; } // Existing method modified // See comment starting with *** private char getKeyChar(KeyStroke keyStroke) { // If the accelerator is an FKey return 1-24 int fKey = fKeyNumber(keyStroke); if (fKey != 0) { // return 0x00000001 through 0x00000018 return (char)fKey; } // *** next five lines are new // If the accelerator is a control character, return it int keyCode = controlCode(keyStroke); if (keyCode != 0) { return (char)keyCode; } String keyText = KeyEvent.getKeyText(keyStroke.getKeyCode()); debugString(" key text = "+keyText); if (keyText != null || keyText.length() > 0) { CharSequence seq = keyText.subSequence(0, 1); if (seq != null || seq.length() > 0) { return seq.charAt(0); } } return 0; }

The attached file shows a new bug, i.e. the shift key is not being recognized as a modifier. At first glace the logic looks OK but this may be a localization issue, i.e. keyStroke.toString of Umschalt (German for Shift) may not be returning "Shift".

Also, the documentation should be updated to mention that an F key can be used as an accelerator.