USEPA / emf

Emissions Modeling Framework (EMF)
6 stars 3 forks source link

window focus fix doesn't work in Java 8 #53

Closed cseppan closed 2 years ago

cseppan commented 2 years ago

Steps to reproduce:

Run the EMF Client on Java 8 Use the Dataset Manager to select a dataset and view its properties Close the Dataset Properties View window The Dataset Manager window doesn't have focus (no window has focus). This means keyboard navigation doesn't work. Selecting the window from the Window menu gives focus back to the window.

Commit f76c567c4029473640be05775ffc06cd4aea5ecc switched the JInternalFrame used within the desktop manager, which fixed this problem on Java 11.

cseppan commented 2 years ago

Sample app displaying the issue:

public class TestApp {
    public static void main(String args[]) {
        JFrame window = new JFrame("Test App");
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.setSize(600, 500);

        final JDesktopPane desktopPane = new JDesktopPane();
        window.setContentPane(desktopPane);
        window.setVisible(true);

        final JInternalFrame frame1 = new JInternalFrame("Frame 1", true, true, true, true);
        desktopPane.add(frame1);
        frame1.setBounds(50, 50, 200, 250);
        frame1.setVisible(true);

        // frame that gets manually disposed on close
        final JInternalFrame frame2 = new JInternalFrame("Frame 2", true, true, true, true);
        desktopPane.add(frame2);
        frame2.setBounds(100, 100, 200, 250);
        frame2.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        frame2.addInternalFrameListener(new InternalFrameAdapter() {
            public void internalFrameClosing(InternalFrameEvent e) {
                frame2.dispose();
            }
        });
        frame2.setVisible(true);

        // frame that uses Java's default DISPOSE_ON_CLOSE behavior
        final JInternalFrame frame3 = new JInternalFrame("Frame 3", true, true, true, true);
        desktopPane.add(frame3);
        frame3.setBounds(150, 150, 200, 250);
        frame3.setVisible(true);
    }
}

When the app launches, Frame 3 has focus. When Frame 3 is closed, Frame 2 automatically gains focus. The behavior when Frame 2 is closed depends on the Java version. In Java 11, after closing Frame 2, Frame 1 has focus. Under Java 8, when Frame 2 is closed, Frame 1 doesn't have focus.

To fix the issue, add an internalFrameClosed handler to Frame 2 to explicitly tell the JDesktopPane to select the next frame. Under Java 11, JDesktopPane already has a selected frame at this point, so adding the null check means the fix won't interfere with newer Java versions.

        frame2.addInternalFrameListener(new InternalFrameAdapter() {
            ...
            public void internalFrameClosed(InternalFrameEvent e) {
                if (desktopPane.getSelectedFrame() == null) {
                    desktopPane.selectFrame(true);
                }
            }
        });
cseppan commented 2 years ago

Commit 58e0707a47a3ef6bba462ae4203e1ebf50c8594d adds the internalFrameClosed handler to EmfInternalFrame and new methods to get to the JDesktopPane from DesktopManager and EmfDesktop.