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

Cannot switch focus between 3 Java Frames using macOS system shortcut Cmd+`

XMLWordPrintable

    • x86
    • os_x

      ADDITIONAL SYSTEM INFORMATION :
      macOS (10.14 Mojave)
      Oracle JDK 8u191 (build 1.8.0_191-b12 / HotSpot build 25.191-b12)
      Oracle JDK 11.0.1 (build 11.0.1+13-LTS / HotSpot build 11.0.1+13-LTS)

      A DESCRIPTION OF THE PROBLEM :
      MacOS default system shortcut 'Move focus to next window' (Cmd+`) cannot switch focus between three Java Frames. Pressing Cmd+` only switches focus between two last open Java Frames.

      It seems that the issue appeared on jdk8u131 and it is reproducible on jdk8u131 - jdk8u191, jdk11.0.1.
      The issue is NOT reproducible on jdk8u121 and on current releases jdk8u202, jdk11.0.2.

      Possible regression of JDK-8169589.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Open three java.awt.Frames
      2. Press Cmd+` three times

      Or please run MoveFocusShortcutTest using Java:
          <JAVA_HOME>/bin/javac MoveFocusShortcutTest.java
          <JAVA_HOME>/bin/java MoveFocusShortcutTest

      Or please run MoveFocusShortcutTest using JTReg:
          <JTREG_HOME>/bin/jtreg -testjdk:<JAVA_HOME> MoveFocusShortcutTest.java

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Focus successively switches between all three Java Frames.

      Please see the MoveFocusShortcutTest output on jdk8u121:

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

      Open test frames
      Window gained focus: TestFrame1
      Window gained focus: TestFrame2
      Window gained focus: TestFrame3
      All frames were opened
      Move focus to the next window
      Window gained focus: TestFrame2
      Move focus to the next window
      Window gained focus: TestFrame1
      Move focus to the next window
      Window gained focus: TestFrame3
      Test PASSED

      Please see the MoveFocusShortcutTest output on jdk11.0.2:

      <jdk-11.0.2.jdk>/Contents/Home/bin/java -showversion MoveFocusShortcutTest
      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)
      Open test frames
      Window gained focus: TestFrame1
      Window gained focus: TestFrame2
      Window gained focus: TestFrame3
      All frames were opened
      Move focus to the next window
      Window gained focus: TestFrame2
      Move focus to the next window
      Window gained focus: TestFrame1
      Move focus to the next window
      Window gained focus: TestFrame3
      Test PASSED
      ACTUAL -
      Focus only switches between two last open Frames.

      Please see the MoveFocusShortcutTest output on jdk8u191:

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

      Open test frames
      Window gained focus: TestFrame1
      Window gained focus: TestFrame2
      Window gained focus: TestFrame3
      All frames were opened
      Move focus to the next window
      Window gained focus: TestFrame2
      Move focus to the next window
      Window gained focus: TestFrame3
      Move focus to the next window
      Window gained focus: TestFrame2
      Exception in thread "main" java.lang.RuntimeException: Test FAILED: Command+` shortcut cannot move focus to the TestFrame(s): 1
      at MoveFocusShortcutTest.main(MoveFocusShortcutTest.java:138)

      Please see the MoveFocusShortcutTest output on jdk11.0.1:

      <jdk-11.0.1.jdk>/Contents/Home/bin/java -showversion MoveFocusShortcutTest
      java version "11.0.1" 2018-10-16 LTS
      Java(TM) SE Runtime Environment 18.9 (build 11.0.1+13-LTS)
      Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.1+13-LTS, mixed mode)
      Open test frames
      Window gained focus: TestFrame1
      Window gained focus: TestFrame2
      Window gained focus: TestFrame3
      All frames were opened
      Move focus to the next window
      Window gained focus: TestFrame2
      Move focus to the next window
      Window gained focus: TestFrame3
      Move focus to the next window
      Window gained focus: TestFrame2
      Exception in thread "main" java.lang.RuntimeException: Test FAILED: Command+` shortcut cannot move focus to the TestFrame(s): 1
      at MoveFocusShortcutTest.main(MoveFocusShortcutTest.java:138)

      ---------- BEGIN SOURCE ----------
      import java.awt.AWTException;
      import java.awt.Frame;
      import java.awt.GraphicsEnvironment;
      import java.awt.Robot;
      import java.awt.Window;
      import java.awt.event.KeyEvent;
      import java.awt.event.WindowAdapter;
      import java.awt.event.WindowEvent;
      import java.util.concurrent.CountDownLatch;
      import java.util.concurrent.TimeUnit;

      /**
       * @test
       * @summary Cmd+` doesn't work
       * @requires (jdk.version.major >= 8 & os.family == "mac")
       * @run main MoveFocusShortcutTest
       */

      /*
       * Description: Test checks that Command+` macOS system shortcut successively switches focus between three Java Frames.
       *
       * Note: Please check that Command+` macOS system shortcut is enabled before launching this test
       * (use system Preferences -> Keyboard -> Shortcuts tab -> Keyboard -> mark 'Move focus to next window' checkbox)
       * MacOS accessibility permission should also be granted on macOS > for the application launching this test, so
       * Java Robot is able to access the keyboard (use System Preferences -> Security&Privacy -> Accessibility -> Privacy).
       */

      public class MoveFocusShortcutTest {

          private static final int PAUSE = 2000;

          private static TestFrame frame1;
          private static TestFrame frame2;
          private static TestFrame frame3;

          private static WindowAdapter frameFocusListener;

          private static Robot robot;

          private static class TestFrame extends Frame {

              private final CountDownLatch frameGainedFocus;

              private TestFrame(String title) {
                  super(title);
                  frameGainedFocus = new CountDownLatch(2);
              }

              private CountDownLatch getLatch() {
                  return frameGainedFocus;
              }
          }

          /*
           * Checks that pressing Command+` successively switches focus between three Java Frames
           */
          public static void main(String[] args) throws AWTException, InterruptedException {

              if (GraphicsEnvironment.isHeadless()) {
                  throw new RuntimeException("ERROR: Cannot execute the test in headless environment");
              }

              frame1 = new TestFrame("TestFrame1");
              frame2 = new TestFrame("TestFrame2");
              frame3 = new TestFrame("TestFrame3");

              frameFocusListener = new WindowAdapter() {
                  @Override
                  public void windowGainedFocus(WindowEvent windowEvent) {
                      Window window = windowEvent.getWindow();
                      try {
                          TestFrame frame = (TestFrame) windowEvent.getWindow();
                          frame.getLatch().countDown();
                          System.out.println("Window gained focus: " + frame.getTitle());
                      } catch (ClassCastException e) {
                          throw new RuntimeException("Unexpected window: " + window);
                      }
                  }
              };

              try {
                  robot = new Robot();
                  robot.setAutoDelay(50);

                  System.out.println("Open test frames");
                  showGUI();

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

                  boolean check1 = (frame1.getLatch().getCount() == 1);
                  boolean check2 = (frame2.getLatch().getCount() == 1);
                  boolean check3 = (frame3.getLatch().getCount() == 1);

                  if (check1 && check2 && check3) {
                      System.out.println("All frames were opened");
                  } else {
                      throw new RuntimeException("Test ERROR: Cannot focus the TestFrame(s): "
                              + getFailedChecksString(check1, check2, check3));
                  }

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

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

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

                  boolean result1 = frame1.getLatch().await(PAUSE, TimeUnit.MILLISECONDS);
                  boolean result2 = frame2.getLatch().await(PAUSE, TimeUnit.MILLISECONDS);
                  boolean result3 = frame3.getLatch().await(PAUSE, TimeUnit.MILLISECONDS);

                  if(result1 && result2 && result3) {
                      System.out.println("Test PASSED");
                  } else {
                      throw new RuntimeException("Test FAILED: Command+` shortcut cannot move focus to the TestFrame(s): "
                              + getFailedChecksString(result1 , result2 , result3));
                  }
              } finally {
                  destroyGUI();
                  /* Waiting for EDT auto-shutdown */
                  Thread.sleep(PAUSE);
              }
          }

          /*
           * Opens test frames
           */
          private static void showGUI() {
              frame1.setSize(400, 200);
              frame2.setSize(400, 200);
              frame3.setSize(400, 200);
              frame1.setLocation(50, 50);
              frame2.setLocation(100, 100);
              frame3.setLocation(150, 150);
              frame1.addWindowFocusListener(frameFocusListener);
              frame2.addWindowFocusListener(frameFocusListener);
              frame3.addWindowFocusListener(frameFocusListener);
              frame1.setVisible(true);
              frame2.setVisible(true);
              frame3.setVisible(true);
          }

          /*
           * Presses Command+` on macOS keyboard
           */
          private static void moveFocusToNextWindow() {
              System.out.println("Move focus to the next window");
              robot.keyPress(KeyEvent.VK_META);
              robot.keyPress(KeyEvent.VK_BACK_QUOTE);
              robot.keyRelease(KeyEvent.VK_BACK_QUOTE);
              robot.keyRelease(KeyEvent.VK_META);
          }

          /*
           * Returns string containing positions of the false values
           */
          private static String getFailedChecksString(boolean ... values) {
              int i = 0;
              String result = "";
              for (boolean value : values) {
                  i++;
                  if(!value) {
                      result += result.isEmpty() ? i : (", " + i);
                  }
              }
              return result;
          }

          /*
           * Disposes test frames
           */
          private static void destroyGUI() {
              frame1.removeWindowFocusListener(frameFocusListener);
              frame2.removeWindowFocusListener(frameFocusListener);
              frame3.removeWindowFocusListener(frameFocusListener);
              frame1.dispose();
              frame2.dispose();
              frame3.dispose();
          }
      }

      ---------- END SOURCE ----------

      FREQUENCY : always


            pardesha Pardeep Sharma
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: