简体   繁体   中英

New window appears sandwiched between parent and child JFrame/JDialog

New windows from other processes open behind a focused JDialog child but in front of the JDialog parent. I would expect new windows to appear in front of the child. None of these windows are declared always on top.

Picture

  • See that app 3 is between app 2 windows
  • Does not matter that it is behind app 1 - always on top, this is expected

应用程式2视窗之间3

Actual order

JDialog (App 1 - always on top)
JFrame (App 2 non modal dialog child of app 2 main)
JDialog (App 3) <=== new window should appear on top of app 2
JFrame (App 2 - main window)

Expected order

JDialog (App 1 - always on top)
JDialog (App 3) <=== new window should appear on top of app 2
JFrame (App 2 non modal dialog child of app 2 main)
JFrame (App 2 - main window)

This problem only happens if

  • there is an existing window from another process that is declared always-on-top, this doesn't have to be Java, I just used Java in the sample below - but issue also happens if you select always on top for say Firefox, gnome-terminal etc.
  • The new window that is opened in a position that is behind the always on top application. Again, doesn't have to be Java application, repeated with Firefox, gnome-terminal.
  • Redhat Linux 6. Not repeatable on Ubuntu 16.04 or Windows 7

If the window is opened slightly to the right (change to newWindow.setBounds(**370**, 20, 0, 200) ) in the sample below, so that it is not behind the always on top window then it appears in front of child.

3在2以上打开

To be clear, this problem occurs between three separate applications, however for simplicity I've recreated it below as a single Java application.

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

        JFrame aot = new JFrame("App 1 - always on top");
        aot.setAlwaysOnTop(true);
        aot.setBounds(50, 50, 300, 40);
        aot.setVisible(true);

        JFrame frame = new JFrame("App 2 - main window");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setBounds(100, 100, 300, 200);
        frame.setVisible(true);

        JDialog child = new JDialog(frame, "App 2 - non-modal child dialog (child)");
        child.setBounds(150, 150, 300, 200);
        child.setVisible(true);

        Thread.sleep(1000);
        JFrame newWindow = new JFrame("App 3");
        newWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        newWindow.setBounds(200, 20, 300, 200);
        // newWindow.setBounds(370, 20, 300, 200);

        newWindow.setVisible(true);
    }
}

Is there any option that can be applied to the JDialog child such that it allows Windows appear above it. The background is that I'm developing the "app 2" application, all the other parts and the Redhat Linux installation are all managed by other third-parties, so cannot be changed easily.

Tried using strict/smart window manager options, but no difference in behaviour

gconftool-2 --set /schemas/apps/metacity/general/focus_new_windows --type string smart
gconftool-2 --set /schemas/apps/metacity/general/focus_new_windows --type string strict

Hacky solutions

  • Show, hide and then show the App 3 window again. In this case it appears above "App 2 child" correctly, although this causes a noticable flicker

Code

newWindow.setVisible(true);
newWindow.setVisible(false);
newWindow.setVisible(true);

In summary there are no nice solutions to this Linux windows management specific issue. All that can be done is to banish always-on-top windows from your application. This is best practice anyway, but difficult when dealing with legacy codebases.

The only other solution of desparation is to do the setVisible() dance.

newWindow.setVisible(true);
newWindow.setVisible(false);
newWindow.setVisible(true);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM