JDK-8315701 : [macos] Regression: KeyEvent has different keycode on different keyboard layouts
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 18,19,20,21
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: os_x
  • Submitted: 2023-09-05
  • Updated: 2024-07-22
  • Resolved: 2023-11-30
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.
JDK 22
22 b27Fixed
Related Reports
Relates :  
Relates :  
Description
Starting from JDK18 KeyEvents started to have different keycode on different keyboard layouts.
Because of that shortcuts (like copy/paste) stopped to work on non-english locales.

Everything works fine in JDKs 17 and older.

It seems like this is the regression produced by this commit: https://github.com/openjdk/jdk/commit/47e7a42594f1c36f71cdf4d383080bf8d616b7e7

With this code
```
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class Example {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            var frame = new JFrame();
            frame.addKeyListener(new KeyListener() {
                @Override
                public void keyTyped(KeyEvent e) {

                }

                @Override
                public void keyPressed(KeyEvent e) {
                    System.out.println("CODE " + KeyEvent.VK_C + " REAL CODE " + e.getKeyCode());
                }

                @Override
                public void keyReleased(KeyEvent e) {

                }
            });
            frame.setSize(new Dimension(200, 200));
            frame.setVisible(true);
        });
    }
}
```

Steps to reproduce:
1. Run the application
2. Change locale to English
3. Press cmd + C 
4. Change locale to Russian (may be on other it will also fail)
5. Press cmd + C

Expected:
CODE 67 REAL CODE 67
printed on both locales
Actual -
CODE 67 REAL CODE 67
is printed on English locale 
CODE 67 REAL CODE 16778305
is printed on Russian locale
Comments
Changeset: a3eb6640 Author: Alisen Chung <achung@openjdk.org> Date: 2023-11-30 16:11:09 +0000 URL: https://git.openjdk.org/jdk/commit/a3eb6640773620331692da40356522ff618c3c44
30-11-2023

Kind of. After JDK-8262945 the extended key code was assigned to the key code: https://github.com/openjdk/jdk/blob/83b01cf3c28bc38b953d6e7e41bb7d730d91179f/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m#L466-L472 Now, with the fix, it is correctly assigned to the extended key code, preserving the key code intact.
29-11-2023

2^24 = 16777216, so it looks like a masking problem.
29-11-2023

With the fix on the review, I get the following output: ~/dev/jdk-dev % ./build/macosx-x64/jdk/bin/java RussianAccelerators.java # Cmd+C and Cmd+V in US keyboard layout CODE 67 REAL CODE 157 ExtendedKeyCode 157 CODE 67 REAL CODE 67 ExtendedKeyCode 67 CODE 67 REAL CODE 86 ExtendedKeyCode 86 # switching to Russian keyboard layout CODE 67 REAL CODE 17 ExtendedKeyCode 17 # Cmd+C and Cmd+V in Russian keyboard layout CODE 67 REAL CODE 157 ExtendedKeyCode 157 CODE 67 REAL CODE 67 ExtendedKeyCode 16778305 CODE 67 REAL CODE 86 ExtendedKeyCode 16778300
29-11-2023

A pull request was submitted for review. URL: https://git.openjdk.org/jdk/pull/16664 Date: 2023-11-14 21:22:37 +0000
14-11-2023

Interestingly, with Alexander's modifications, I get different output on macOS with Russian keyboard layout: ~/dev/jdk-dev % ./build/macosx-x64/jdk/bin/java RussianAccelerators.java CODE 67 REAL CODE 157 ExtendedKeyCode 157 CODE 67 REAL CODE 16778305 ExtendedKeyCode 67 CODE 67 REAL CODE 16778300 ExtendedKeyCode 86 For pressing Cmd+C followed by Cmd+V — the codes are reversed in mainline.
07-11-2023

I can confirm that @Override public void keyPressed(KeyEvent e) { System.out.println("CODE " + KeyEvent.VK_C + " REAL CODE " + e.getKeyCode() + " ExtendedKeyCode " + e.getExtendedKeyCode()); } prints on Linux, Windows and macos(without the JDK-8262945) CODE 67 REAL CODE 67 ExtendedKeyCode 67 // English keyboard layout CODE 67 REAL CODE 67 ExtendedKeyCode 16778305 // Russian keyboard layout macos with the JDK-8262945 fix prints CODE 67 REAL CODE 67 ExtendedKeyCode 67 // English keyboard layout CODE 67 REAL CODE 16778305 ExtendedKeyCode 16778305 // Russian keyboard layout Moreover the java/awt/event/KeyEvent/AcceleratorTest/AcceleratorTest.html test does not pass with the JDK-8262945 fix on macos: " Ensure you have Russian keyboard layout as a currently active.", "(1) Press Ctrl+\u0411 (a key with \",<\" on it) ", "(2) Find a . (period) in this layout (perhaps \"/?\" or \"7&\" key).", "Press Ctrl+.", "(3) Press Crtl+ regular English . (period) key (on \".>\" )", "(4) Press Ctrl+ key with English N.", "(5) Press Alt+\u042E (key with \".>\")", "(6) Press Alt+\u0436 (key with \";:\")", "If all expected commands will be fired, look for message", "\"All tests passed\"" No action fired for items 2, 4, 5. For item 6 getActionCommand() returns "«" instead of "ж". So it looks like we should revert JDK-8262945 and fix the accelerators using info from the ExtendedKeyCode.
05-10-2023