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

[macos] Press&Hold macOS feature doesn't work when hold down an accent key using Robot

    Details

    • Subcomponent:
    • Understanding:
      Cause Known
    • Introduced In Build:
      b127
    • Introduced In Version:
      9
    • CPU:
      x86
    • OS:
      os_x

      Description

      ADDITIONAL SYSTEM INFORMATION :
      macOS >= 10.7
      Oracle JDK build 11.0.2+7-LTS / HotSpot build 11.0.2+7-LTS

      A DESCRIPTION OF THE PROBLEM :
      Accents popup menu should appear instead of the key repeat when holding down an accent key with Java Robot if ApplePressAndHoldEnabled=1 (default value for macOS >= 10.7).

      REGRESSION : Last worked in version 8u202

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Check that ApplePressAndHoldEnabled=1 using 'defaults read -g ApplePressAndHoldEnabled'
      If ApplePressAndHoldEnabled=0 then set it to 1 using 'defaults write -g ApplePressAndHoldEnabled -boolean true’

      2. Using several Robot keyPresses hold down a key that can be accented, for example, A for English keyboard layout:

      for (int i = 0; i < 10; i++) {
          robot.keyPress(KeyEvent.VK_A);
      }
      robot.keyRelease(KeyEvent.VK_A);

      Note: MacOS accessibility permission should be granted for the application launching the java test (IDE, Terminal), so Java Robot may access the keyboard.

      Or just run the HoldDownAccentKey test (using Java or JTReg):

      <JAVA_HOME>/bin/javac HoldDownAccentKey.java
      <JAVA_HOME>/bin/java HoldDownAccentKey

      or

      <JTREG_HOME>/bin/jtreg -testjdk:<JAVA_HOME> HoldDownAccentKey.java

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Accent menu popup appears, so user may select an accent

      <jdk1.8.0_202.jdk>/Contents/Home/bin/java -showversion HoldDownAccentKey
      java version "1.8.0_202"
      Java(TM) SE Runtime Environment (build 1.8.0_202-b08)
      Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)

      ApplePressAndHoldEnabled = 1
      TEST PASSED
      ACTUAL -
      A key is pressed several times

      <jdk-11.0.2.jdk>/Contents/Home/bin/java -showversion HoldDownAccentKey

      java version "11.0.2" 2018-10-16 LTS
      Java(TM) SE Runtime Environment 18.9 (build 11.0.2+7-LTS)
      Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.2+7-LTS, mixed mode)
      ApplePressAndHoldEnabled = 1
      Exception in thread "main" java.lang.RuntimeException: TEST FAILED: Holding a key down causes the key repeat instead of accent menu popup
      at HoldDownAccentKey.main(HoldDownAccentKey.java:144)

      ---------- BEGIN SOURCE ----------
      import java.awt.AWTException;
      import java.awt.Frame;
      import java.awt.GraphicsEnvironment;
      import java.awt.Robot;
      import java.awt.TextField;
      import java.awt.event.KeyEvent;
      import java.awt.event.TextListener;
      import java.io.BufferedReader;
      import java.io.IOException;
      import java.io.InputStreamReader;

      /**
       * @test
       * @summary Regression test for: Press&Hold macOS feature doesn't work when holding down an accent key using Robot
       * @requires (jdk.version.major >= 8 & os.family == "mac")
       * @run main HoldDownAccentKey
       */

      /*
       * Description: Tests that accents popup menu appears instead of the key repeat
       * when holding down an accent key with Java Robot if ApplePressAndHoldEnabled=1.
       *
       * Note: Test works with English keyboard layout.
       * Test requires macOS system property ApplePressAndHoldEnabled=1 (default value for macOS >= 10.7).
       * MacOS accessibility permission should also be granted for the application launching this test, so
       * Java Robot is able to access keyboard (use System Preferences -> Security&Privacy -> Privacy tab -> Accessibility).
       */

      public class HoldDownAccentKey {

          private static final int SAMPLE_KEY = KeyEvent.VK_A;
          private static final int REPEAT_NUM = 10;

          private static final String SAMPLE_RESULT="à";
          private static final String SAMPLE_REPEAT = "aaaaaaaaaa1";

          private static final int PAUSE = 2000;

          private static volatile String result="";

          /*
           * Returns macOS major and minor version as an integer
           */
          private static int getMajorMinorMacOsVersion() {
              int version = 0;
              String versionProp = System.getProperty("os.version");
              if (versionProp != null && !versionProp.isEmpty()) {
                  String[] versionComponents = versionProp.split("\\.");
                  String majorMinor = versionComponents[0];
                  if (versionComponents.length > 1) {
                      majorMinor += versionComponents[1];
                  }
                  try {
                      version = Integer.parseInt(majorMinor);
                  } catch (NumberFormatException nfexception) {
                      // Do nothing
                  }
              }
              return version;
          }

          /*
           * Returns ApplePressAndHoldEnabled system property value
           */
          private static String getApplePressAndHoldValue() throws IOException, InterruptedException {
              Process readDefaults = new ProcessBuilder("defaults", "read", "-g", "ApplePressAndHoldEnabled")
                      .redirectError(ProcessBuilder.Redirect.INHERIT).start();
              readDefaults.waitFor();

              try (BufferedReader reader = new BufferedReader(new InputStreamReader(readDefaults.getInputStream()))) {
                  return reader.readLine();
              }
          }

          /*
           * Checks that accents popup menu appears instead of the key repeat
           * when holding down an accent key with Java Robot if ApplePressAndHoldEnabled=1
           */
          public static void main(String[] args) throws AWTException, InterruptedException, IOException {
              if (GraphicsEnvironment.isHeadless()) {
                  throw new RuntimeException("ERROR: Cannot execute the test in headless environment");
              }

              final int osVersion = getMajorMinorMacOsVersion();
              if (osVersion == 0) {
                  throw new RuntimeException("ERROR: Cannot determine MacOS version");
              } else if (osVersion < 107) {
                  System.out.println("TEST SKIPPED: No Press&Hold feature for Snow Leopard or lower MacOS version");
                  return;
              }

              final String applePressAndHoldValue = getApplePressAndHoldValue();
              System.out.println("ApplePressAndHoldEnabled = " + applePressAndHoldValue);
              if (!"1".equals(applePressAndHoldValue)) {
                  throw new RuntimeException("TEST ERROR: ApplePressAndHoldEnabled system property must be set to 1");
              }

              final Frame frame = new Frame("Test Frame");
              final TextField textField = new TextField();
              final TextListener textListener = (e -> result = textField.getText());

              try {
                  textField.addTextListener(textListener);
                  frame.add(textField);
                  frame.setSize(400, 200);
                  frame.setLocation(100, 100);
                  frame.setVisible(true);

                  Robot robot = new Robot();
                  robot.setAutoDelay(50);
                  robot.waitForIdle();

                  // Hold down sample key so accents popup menu may appear
                  for (int i = 0; i < REPEAT_NUM; i++) {
                      robot.keyPress(SAMPLE_KEY);
                  }
                  robot.keyRelease(SAMPLE_KEY);

                  // Select the first accent
                  robot.keyPress(KeyEvent.VK_1);
                  robot.keyRelease(KeyEvent.VK_1);

                  Thread.sleep(PAUSE);
                  robot.waitForIdle();

                  if (SAMPLE_RESULT.equals(result)) {
                      System.out.println("TEST PASSED");
                  } else if (SAMPLE_REPEAT.equals(result)) {
                      throw new RuntimeException("TEST FAILED: Holding a key down " +
                              "causes the key repeat instead of accent menu popup");
                  } else {
                      throw new RuntimeException("TEST ERROR: Unexpected input value: " + result);
                  }

              } finally {
                  textField.removeTextListener(textListener);
                  frame.dispose();
                  /* Waiting for EDT auto-shutdown */
                  Thread.sleep(PAUSE);
              }
          }
      }
      ---------- END SOURCE ----------

      FREQUENCY : always


        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                serb Sergey Bylokhov
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                4 Start watching this issue

                Dates

                • Created:
                  Updated: