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

Components can't recive focus after transfering focus programmatically

    XMLWordPrintable

Details

    • x86_64
    • linux_ubuntu, windows_7

    Description

      FULL PRODUCT VERSION :
      java version "1.8.0_66"
      Java(TM) SE Runtime Environment (build 1.8.0_66-b17)
      Java HotSpot(TM) 64-Bit Server VM (build 25.66-b17, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      Linux DEKA01-B04014-PC0004 3.13.0-68-generic #111-Ubuntu SMP Fri Nov 6 18:17:06 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

      A DESCRIPTION OF THE PROBLEM :
      There are two actions mapped onto keys.

      The first action (MessWithFocus in the provided source code) does some long lasting work (simulated by sleeping for 2 seconds), then transfers the focus programmatically twice. (In our actual application, the first focus transfer is made by client code (e.g. by making the current focusowner un-focusable). The second transfer is made by the action itself.)

      The second action (ShowDialog) opens a modal dialog.

      If the user presses the key that activates the second action, while the first action is sleeping, all components become unfocusable. The components are back to normal after a new dialog has been shown (by pressing the button in the provided example).

      REGRESSION. Last worked in version 7u80

      ADDITIONAL REGRESSION INFORMATION:
      java version "1.7.0_85"
      OpenJDK Runtime Environment (IcedTea 2.6.1) (7u85-2.6.1-5ubuntu0.14.04.1)
      OpenJDK 64-Bit Server VM (build 24.85-b03, mixed mode)


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Run the provided program using Java 8. The application has four textfields labeld '0' to '3'. Text field 0 hat the focus. Press 'f' and 'a' keys in quick succession (within 2 seconds). After 2 seconds a dialog pops up. Press 'ok'.

      The 'f'-key is mapped onto an action that sleeps for 2 seconds and then transfers focus two times. The 'a'-key and the button are mapped onto an action that shows a dialog.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The focus should be transferred onto the text field labeld 2.
      ACTUAL -
      In Java 8, no element has the focus. No element can recieve the focus. Neither by using the mouse nor by using the tab-key. Not the text tields and not the button. Only after calling up a modal dialog again (by clicking on the button) are the text fields focusable again.

      In Java 7, no element has the focus. But the elements can still receive the focus by clicking on them.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.awt.Dimension;
      import java.awt.GridLayout;
      import java.awt.event.ActionEvent;

      import javax.swing.AbstractAction;
      import javax.swing.JButton;
      import javax.swing.JFrame;
      import javax.swing.JOptionPane;
      import javax.swing.JPanel;
      import javax.swing.JTextArea;
      import javax.swing.JTextField;
      import javax.swing.KeyStroke;
      import javax.swing.SwingUtilities;
      import javax.swing.text.JTextComponent;


      public class FocusBug implements Runnable {
          
          private class ShowDialog extends AbstractAction {
              public final KeyStroke keyStroke;

              public ShowDialog() {
                  super("show dialog");
                  this.keyStroke = KeyStroke.getKeyStroke('a');
              }

              @Override
              public void actionPerformed(final ActionEvent e) {
                  JOptionPane.showMessageDialog(frame, "Some Dialog.");
              }

          }
          
          private class MessWithFocus extends AbstractAction {
              public final KeyStroke keyStroke;

              public MessWithFocus() {
                  super();
                  this.keyStroke = KeyStroke.getKeyStroke('f');
              }

              @Override
              public void actionPerformed(final ActionEvent e) {

                  try {
                      Thread.sleep(2000);
                  } catch (InterruptedException e1) {
                  }
                  
                  tpArray[1].requestFocusInWindow();
                  tpArray[2].requestFocusInWindow();
              }
          }

          private static final int NUM_TP = 4;
          private JFrame frame;
          private JTextField[] tpArray;

          public FocusBug() {
              frame = new JFrame("FocusBug");
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              frame.setPreferredSize(new Dimension(500, 500));

              JPanel panel = new JPanel();
              GridLayout mgr = new GridLayout(6, 0);
              mgr.setHgap(5); mgr.setVgap(5);
              panel.setLayout(mgr);
              
              tpArray = new JTextField[NUM_TP];
              for (int i = 0; i < NUM_TP; i++) {
                  tpArray[i] = new JTextField(Integer.toString(i));
              }

              ShowDialog showDialog = new ShowDialog();
              MessWithFocus messFocus = new MessWithFocus();
              
              for (JTextComponent cmp : tpArray) {
                  cmp.getKeymap().addActionForKeyStroke(showDialog.keyStroke, showDialog);
                  cmp.getKeymap().addActionForKeyStroke(messFocus.keyStroke, messFocus);
                  
                  panel.add(cmp);
              }
              
              JButton button = new JButton("show dialog");
              button.setAction(showDialog);
              panel.add(button);
              
              JTextArea instructions = new JTextArea(
                      "Put Cursor in text field 0. Press 'f' and 'a' in succession.\n" +
                      "Press any button on the dialog.\n" +
                      "Now none of the text fields can recieve the focus.\n" +
                      "Text fields are focusable again after the button was pressed.");
              instructions.setEditable(false);
              panel.add(instructions);
              
              frame.setContentPane(panel);

              frame.pack();
          }

          @Override
          public void run() {
              frame.setVisible(true);
          }
              
          public static void main(final String[] args) {
              FocusBug app = new FocusBug();
              SwingUtilities.invokeLater(app);
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      I tried to disable the type-ahead feature in the KeyboardFocusManager by using the following run-Method instead of the one in the provided source code:

          @Override
          public void run() {
              KeyboardFocusManager.setCurrentKeyboardFocusManager(new DefaultKeyboardFocusManager() {
                  @Override
                  protected void enqueueKeyEvents(final long after, final Component untilFocused) {
                      
                  }
              });
              frame.setVisible(true);
          }

      The result is that after pressing 'f' and 'a' keys as described, the 2-labeld text field has the focus. But I don't know why this workaround works or what the consequences might be.

      Attachments

        Activity

          People

            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

              Created:
              Updated: