JBR-5630: vmoption to change dead key reporting behavior on macOS

This commit is contained in:
Nikita Tsarev
2023-06-02 15:26:15 +02:00
parent d9e8213d6a
commit 34f54e4e9e
13 changed files with 50 additions and 31 deletions

View File

@@ -192,7 +192,6 @@ final class CPlatformResponder {
int jkeyCode = KeyEvent.VK_UNDEFINED;
int jkeyLocation = KeyEvent.KEY_LOCATION_UNKNOWN;
boolean spaceKeyTyped = false;
boolean charsReserved = false;
char testChar = KeyEvent.CHAR_UNDEFINED;
@@ -213,27 +212,15 @@ final class CPlatformResponder {
// That field is only guaranteed to be meaningful for KEY_TYPED events, so let's not overthink it.
// Please note: this character is NOT used to construct extended key codes, that happens
// inside the NSEvent.nsToJavaKeyInfo function.
char ch = chars.charAt(chars.length() - 1);
if (chars.length() == 1) {
// NSEvent.h declares this range of characters to signify various function keys
// This is a subrange of the Unicode private use area.
// No builtin key layouts normally produce any characters within this range, except when
// pressing the corresponding function keys.
charsReserved = ch >= 0xF700 && ch <= 0xF7FF;
}
testChar = chars.charAt(chars.length() - 1);
// Check if String chars contains SPACE character.
if (chars.trim().isEmpty()) {
spaceKeyTyped = true;
}
if (!charsReserved) {
testChar = ch;
}
}
int[] in = new int[] {keyCode, KeyEventProcessing.useNationalLayouts ? 1 : 0};
int[] in = new int[] {keyCode, KeyEventProcessing.useNationalLayouts ? 1 : 0, KeyEventProcessing.reportDeadKeysAsNormal ? 1 : 0};
int[] out = new int[2]; // [jkeyCode, jkeyLocation]
NSEvent.nsToJavaKeyInfo(in, out);

View File

@@ -607,6 +607,7 @@ struct KeyCodeTranslationResult TranslateKeyCodeUsingLayout(TISInputSourceRef la
*/
static void
NsCharToJavaVirtualKeyCode(unsigned short key, const BOOL useNationalLayouts,
const BOOL reportDeadKeysAsNormal,
jint *keyCode, jint *keyLocation)
{
// This is going to be a lengthy explanation about what it is that we need to achieve in this function.
@@ -709,7 +710,7 @@ NsCharToJavaVirtualKeyCode(unsigned short key, const BOOL useNationalLayouts,
struct KeyCodeTranslationResult translatedKey = TranslateKeyCodeUsingLayout(underlyingLayout, key);
// Test whether this key is dead.
if (translatedKey.isDead) {
if (translatedKey.isDead && !reportDeadKeysAsNormal) {
for (const struct CharToVKEntry *map = charToDeadVKTable; map->c != 0; ++map) {
if (translatedKey.character == map->c) {
*keyCode = map->javaKey;
@@ -736,7 +737,7 @@ NsCharToJavaVirtualKeyCode(unsigned short key, const BOOL useNationalLayouts,
unichar ch = 0;
if (translatedKey.isTyped) {
if (translatedKey.isDead || translatedKey.isTyped) {
ch = translatedKey.character;
}
@@ -957,12 +958,14 @@ JNI_COCOA_ENTER(env);
// in = [keyCode, useNationalLayouts]
jshort keyCode = (jshort)data[0];
BOOL useNationalLayouts = (data[1] != 0);
BOOL reportDeadKeysAsNormal = (data[2] != 0);
jint jkeyCode = java_awt_event_KeyEvent_VK_UNDEFINED;
jint jkeyLocation = java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN;
NsCharToJavaVirtualKeyCode((unsigned short)keyCode,
useNationalLayouts,
reportDeadKeysAsNormal,
&jkeyCode, &jkeyLocation);
// out = [jkeyCode, jkeyLocation];

View File

@@ -14,6 +14,13 @@ public class KeyEventProcessing {
System.getProperty(useNationalLayoutsOption,
FontUtilities.isMacOSX ? "true" : "false"));
// Report dead keys (such as VK_DEAD_GRAVE) as normal keys (such as VK_BACK_QUOTE)
public final static String reportDeadKeysAsNormalOption = "com.sun.awt.reportDeadKeysAsNormal";
@Native
public final static boolean reportDeadKeysAsNormal = "true".equals(
System.getProperty(reportDeadKeysAsNormalOption,
FontUtilities.isMacOSX ? "true" : "false"));
// Used on windows to emulate latin OEM keys on cyrillic keyboards
public final static String useLatinNonAlphaNumKeycodesOption = "com.sun.awt.useLatinNonAlphaNumKeycodes";
@Native

View File

@@ -48,7 +48,8 @@ public class InputMethodTest {
private enum TestCases {
DeadKeysTest (new DeadKeysTest()),
KeyCodesTest (new KeyCodesTest()),
NextAppWinKeyTest (new NextAppWinKeyTest()),
NextAppWinKeyTestDead (new NextAppWinKeyTest(true)),
NextAppWinKeyTestNormal (new NextAppWinKeyTest(false)),
PinyinCapsLockTest (new PinyinCapsLockTest()),
PinyinFullWidthPunctuationTest (new PinyinFullWidthPunctuationTest()),
PinyinHalfWidthPunctuationTest (new PinyinHalfWidthPunctuationTest()),

View File

@@ -25,7 +25,7 @@
* @test
* @summary Regression test for JBR-5173 macOS keyboard support rewrite
* @modules java.desktop/sun.lwawt.macosx
* @run main InputMethodTest KeyCodesTest
* @run main/othervm -Dcom.sun.awt.reportDeadKeysAsNormal=false InputMethodTest KeyCodesTest
* @requires (jdk.version.major >= 8 & os.family == "mac")
*/

View File

@@ -25,7 +25,8 @@
* @test
* @summary Regression test for JBR-5469 Something weird going on with Cmd+Backtick / Cmd+Dead Grave
* @modules java.desktop/sun.lwawt.macosx
* @run main/othervm -Dapple.awt.captureNextAppWinKey=true InputMethodTest NextAppWinKeyTest
* @run main/othervm -Dapple.awt.captureNextAppWinKey=true -Dcom.sun.awt.reportDeadKeysAsNormal=false InputMethodTest NextAppWinKeyTestDead
* @run main/othervm -Dapple.awt.captureNextAppWinKey=true -Dcom.sun.awt.reportDeadKeysAsNormal=true InputMethodTest NextAppWinKeyTestNormal
* @requires (jdk.version.major >= 8 & os.family == "mac")
*/
@@ -37,6 +38,12 @@ import java.awt.event.FocusListener;
import static java.awt.event.KeyEvent.*;
public class NextAppWinKeyTest implements Runnable {
private final boolean deadKeys;
public NextAppWinKeyTest(boolean deadKeys) {
this.deadKeys = deadKeys;
}
@Override
public void run() {
var extraFrame = new JFrame();
@@ -62,12 +69,12 @@ public class NextAppWinKeyTest implements Runnable {
InputMethodTest.section("US-Intl");
InputMethodTest.layout("com.apple.keylayout.USInternational-PC");
InputMethodTest.type(VK_BACK_QUOTE, META_DOWN_MASK);
InputMethodTest.expectKeyPress(VK_DEAD_GRAVE, KEY_LOCATION_STANDARD, META_DOWN_MASK, false);
InputMethodTest.expectKeyPress(deadKeys ? VK_DEAD_GRAVE : VK_BACK_QUOTE, KEY_LOCATION_STANDARD, META_DOWN_MASK, false);
InputMethodTest.section("French");
InputMethodTest.layout("com.apple.keylayout.French");
InputMethodTest.type(VK_BACK_SLASH, META_DOWN_MASK);
InputMethodTest.expectKeyPress(VK_DEAD_GRAVE, KEY_LOCATION_STANDARD, META_DOWN_MASK, false);
InputMethodTest.expectKeyPress(deadKeys ? VK_DEAD_GRAVE : VK_BACK_QUOTE, KEY_LOCATION_STANDARD, META_DOWN_MASK, false);
extraFrame.setVisible(false);
extraFrame.dispose();

View File

@@ -60,10 +60,10 @@ public class Key {
// Key that generates VK_ code when using a US keyboard layout also generates a unique code for other layout.
// Test firstly determines char mapped to the key on the current layout
// and then uses KeyEvent.getExtendedKeyCodeForChar(c) to get the key code.
int getKeyCode() {
int getKeyCode(boolean ignoreDead) {
KeyChar keyChar = mappedKeyChars.getKeyChar();
char ch = keyChar.getChar();
if (keyChar.isDead() && deadKeyCodesMap.containsKey(ch)) {
if (!ignoreDead && keyChar.isDead() && deadKeyCodesMap.containsKey(ch)) {
// KeyEvent.getExtendedKeyCodeForChar(ch) does not return corresponding VK_ constant for dead keys
return deadKeyCodesMap.get(ch);
} else {
@@ -71,6 +71,10 @@ public class Key {
}
}
int getKeyCode() {
return getKeyCode(false);
}
// Returns key char for the current layout
public char getChar(Modifier modifier) {
return mappedKeyChars.getKeyChar(modifier).getChar();

View File

@@ -27,7 +27,7 @@
* @summary Regression test for IDEA-165950: National keyboard layouts support
* @requires (jdk.version.major >= 8 & os.family == "mac")
* @modules java.desktop/sun.lwawt.macosx
* @run main NationalLayoutTest ABC
* @run main/othervm -Dcom.sun.awt.reportDeadKeysAsNormal=false NationalLayoutTest ABC
*/
/*

View File

@@ -26,7 +26,8 @@
* @summary Regression test for IDEA-165950: National keyboard layouts support
* @requires (jdk.version.major >= 8 & os.family == "mac")
* @modules java.desktop/sun.lwawt.macosx
* @run main NationalLayoutTest FRENCH_PC
* @run main/othervm -Dcom.sun.awt.reportDeadKeysAsNormal=false NationalLayoutTest FRENCH_PC
* @run main/othervm -Dcom.sun.awt.reportDeadKeysAsNormal=true NationalLayoutTest nodead FRENCH_PC
*/
/*

View File

@@ -26,7 +26,8 @@
* @summary Regression test for IDEA-165950: National keyboard layouts support
* @requires (jdk.version.major >= 8 & os.family == "mac")
* @modules java.desktop/sun.lwawt.macosx
* @run main NationalLayoutTest GERMAN
* @run main/othervm -Dcom.sun.awt.reportDeadKeysAsNormal=false NationalLayoutTest GERMAN
* @run main/othervm -Dcom.sun.awt.reportDeadKeysAsNormal=true NationalLayoutTest nodead GERMAN
*/
/*

View File

@@ -26,7 +26,8 @@
* @summary Regression test for IDEA-165950: National keyboard layouts support
* @requires (jdk.version.major >= 8 & os.family == "mac")
* @modules java.desktop/sun.lwawt.macosx
* @run main NationalLayoutTest SPANISH_ISO
* @run main/othervm -Dcom.sun.awt.reportDeadKeysAsNormal=false NationalLayoutTest SPANISH_ISO
* @run main/othervm -Dcom.sun.awt.reportDeadKeysAsNormal=true NationalLayoutTest nodead SPANISH_ISO
*/
/*

View File

@@ -26,7 +26,8 @@
* @summary Regression test for IDEA-165950: National keyboard layouts support
* @requires (jdk.version.major >= 8 & os.family == "mac")
* @modules java.desktop/sun.lwawt.macosx
* @run main NationalLayoutTest US_INTERNATIONAL_PC
* @run main/othervm -Dcom.sun.awt.reportDeadKeysAsNormal=false NationalLayoutTest US_INTERNATIONAL_PC
* @run main/othervm -Dcom.sun.awt.reportDeadKeysAsNormal=true NationalLayoutTest nodead US_INTERNATIONAL_PC
*/
/*

View File

@@ -99,6 +99,7 @@ import java.util.stream.Collectors;
public class NationalLayoutTest {
private static final String MANUAL= "manual";
private static final String NODEAD = "nodead";
private static final int PAUSE = 2000;
@@ -113,6 +114,7 @@ public class NationalLayoutTest {
private static boolean jbr = true;
private static boolean autoTest = true;
private static boolean showKeyCodeHex = false;
private static boolean noDeadKeys = false;
private static Frame mainFrame;
@@ -145,7 +147,7 @@ public class NationalLayoutTest {
// Check if program arguments contain known layouts to test
List<Layout> layoutList = new ArrayList();
for (String arg : args) {
if(!arg.equals(MANUAL)) {
if(!arg.equals(MANUAL) && !arg.equals(NODEAD)) {
try {
layoutList.add(Layout.valueOf(arg));
} catch (IllegalArgumentException e) {
@@ -173,6 +175,10 @@ public class NationalLayoutTest {
autoTest = false;
}
if (Arrays.asList(args).contains(NODEAD)) {
noDeadKeys = true;
}
String initialLayoutName = null;
try {
// Create test GUI
@@ -413,7 +419,7 @@ public class NationalLayoutTest {
Key key = layoutKey.getKey();
// Obtain the key code for the current layout
int keyCode = key.getKeyCode();
int keyCode = key.getKeyCode(noDeadKeys);
// Append input area with the modifiers + key under test
if(!modifier.isEmpty()) {