0

My JDialog is not focused when the Java program is not in the front in OSX. How do I achieve this?

I have the following test program to illustrate the scenario (at the bottom), running using javac Test.java && java Test from a terminal.

When the terminal output "Started first", it will change focus to the Java program. I remove focus from the launched Java program by clicking on the terminal (or some other program). The second JDialog shown with "Second test" text will not be focused. This is the same even if I set dialog.setAlwaysOnTop(true);

The JDialog with "Second test" text is correctly focused when I leave the Java program stay on top after seeing "Started first" (i.e. not clicking somewhere else so that the launched Java program is on top).

Note that my Java program doesn't have a Swing UI. It runs in the background and pops up JDialog to take user input. This works fine on both Windows and Linux (the created JDialog is focused regardless of which application is in focus at the time).

public class Test {
    public static void main(String[] args) throws Exception {

        Thread t = new Thread() {
            @Override
            public void run() {
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        launch("First test");
                    }
                });
            }
        };
        Thread t2 = new Thread() {
            @Override
            public void run() {
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        launch("Second test");
                    }
                });
            }
        };

        t.start();
        System.out.println("Started first");
        Thread.sleep(5000);
        System.out.println("Started second");
        t2.start();
    }

    private static void launch(String title) {
        System.out.println("Showing");
        System.out.println(Thread.currentThread().getName());

        final JDialog dialog = new JDialog(null, "Test", ModalityType.APPLICATION_MODAL);
        dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        final JTextField searchBar = new JTextField(title);
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        panel.add(searchBar);
        dialog.add(panel);
        dialog.pack();
        dialog.setLocationRelativeTo(null);
        searchBar.requestFocus();
        SwingUtilities.invokeLater(new Runnable() {  
            public void run() { 
                searchBar.requestFocus();
            }
        });
        dialog.setVisible(true);
        System.out.println("Result is " + searchBar.getText());
    }
}
vda8888
  • 689
  • 1
  • 8
  • 19
  • Don't know if will make a difference but you should be using `requestFocusInWindow()` to typically set focus on a Swing component. Also, it is not recommended, but maybe `grabFocus()` will work. Read the API for the differences between the two methods. – camickr Nov 04 '19 at 02:09
  • I just tried both requestFocusInWindow() and grabFocus() and both have the same problem in the question. – vda8888 Nov 04 '19 at 03:38
  • I'm not entirely sure, but perhaps this is what you want: see my answer [here](https://stackoverflow.com/a/34694266/243373). – TT. Nov 04 '19 at 08:39

1 Answers1

0

I ended up using TT answer here.

Basically the idea is to use java.awt.Robot to move the mouse and click on the popup dialog to gain focus.

It works most of the time, but mouse movement is weird when you have multiple screens so special case handling is needed.

vda8888
  • 689
  • 1
  • 8
  • 19