Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Focus issues with java7 modal dialogs on mac osx

I've been validating a swing application that runs on an applet for mac osx.

During this validation I found the following issues with the modal dialogs:

  1. When a dialog is open and is setModal(true) it blocks the content of the root window, but if you click somewhere on the root window, the dialog goes under it, but it should remain on the top of the root window.
  2. If the dialog has a JTextInputField it does not receive focus even when you click on it.

So I created a small program to show the problem. Can you please help me to understand what is wrong here?

package com.macosx.tests;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class DialogExample extends JApplet{

    private static final long serialVersionUID = 1L;
    private JPanel panel;
    private JButton openDialogBtn;

    private void doStart() {
        panel = new JPanel();
        panel.setPreferredSize(new Dimension(500,500));

        openDialogBtn = new JButton("open dialog");
        openDialogBtn.addActionListener(new ActionListener(){

            @Override
            public void actionPerformed(ActionEvent arg0) {
                ModalDialog dialog = new ModalDialog(panel, true);
                dialog.setVisible(true);
            }

        });
        panel.add(openDialogBtn);
        setContentPane(panel);
    }


    class ModalDialog extends JDialog {
        private static final long serialVersionUID = 1L;

        public ModalDialog(Component parent, boolean modal) {
            Dimension dimensionParentFrame = parent.getSize();
            setSize(new Dimension((parent == null) ? 300 : dimensionParentFrame.width / 2, 75));

            setModal(modal);
            setModalityType(ModalityType.APPLICATION_MODAL);

            JTextField txtField = new JTextField();
            add(txtField, BorderLayout.CENTER);
        }
    }


    @Override
    public void start() {
        try {
            SwingUtilities.invokeAndWait(new Runnable() {
                public void run() {
                    doStart();
                }
            });
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

}

Use the above to create a .jar file (test.jar). Once that is done, create a html file with the following content:

<html>
<head>
<title>Dialog test Applet</title>
</head>
<body>
<applet id="DialogTestApplet" height="800" width="600"
  code="com.macosx.tests.DialogExample"
  archive="test.jar">
</applet>
</div>
</body>
</html>

When this is done, run the html file. You'll see an applet with a gray background and with a button. Then try to:

  1. click on the button to open the dialog. After that, click somewhere on the gray area: the dialog goes under the browser window but it should remain on the top, right?
  2. click on the button to open the dialog. After that click on the textfield of the dialog and try to write something: the textdialog does not receive focus.

So, what am I doing wrong here? Can someone with a mac computer test this please?

Thanks

Specs:

java.vendor    Oracle Corporation
java.version   1.7.0_07
os.name        Mac OS X
os.version     10.7.4

browser        firefox 15

NOTE: please note that this is only happening when the applet runs on the browser and only on mac osx.

like image 896
Luis Gonçalves Avatar asked Sep 05 '12 09:09

Luis Gonçalves


4 Answers

I found another workaround. When the window is opened, show an optionpane for a few milliseconds and close it. It give the focus to the optionpane and then back to the dialog, allowing to ignore the bug.

Add this snipet of code to your dialog constructor and it should work:

addWindowListener(new WindowAdapter(){
public void windowOpened(WindowEvent e){
    JOptionPane pane = new JOptionPane();
    final JDialog dialog = pane.createDialog("Please Wait");
    Timer timer = new Timer(50, new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            dialog.dispose();
        }
    });
timer.setRepeats(false);
timer.start();
dialog.setVisible(true);
}
like image 92
Benoit Connault Avatar answered Nov 01 '22 15:11

Benoit Connault


You should put an "owner" window on your ModalDialog. To do that, you must call super(owner) in your ModalDialog constructor and you can retrieve the parent window of your component parent with SwingUtilities.getWindowAncestor(parent).

like image 23
Guillaume Polet Avatar answered Nov 01 '22 17:11

Guillaume Polet


  • not Mac/OSX user but this is common issue about Focus and JDialog,

  • there are another issues in the case that JDialog is created on Runtime,

  • Focus is asynchronous based on properties came from Native OS

  • create this JDialog only once time and re_use this container for another action

  • JDialog#setVisible should be wrapped into invokeLater() too

  • is possible to force the Focus by JTextField#setText(JTextField#getText()) wrapped into invokeLater()

  • there is Dialog Focus, one of great workaround by @camickr

like image 35
mKorbel Avatar answered Nov 01 '22 16:11

mKorbel


I confirm, I have the same bug with an old applet running in JDK7 on OS X. As the poster mentioned, the bug is seen only with the applet running in the browser (ff) and not with the appletviewer.

like image 43
Yves G. Avatar answered Nov 01 '22 15:11

Yves G.