eclipse-platform / eclipse.platform.swt

Eclipse SWT
https://www.eclipse.org/swt/
Eclipse Public License 2.0
112 stars 134 forks source link

Linux: modal dialog shell stuck behind parent shell #748

Open tmssngr opened 1 year ago

tmssngr commented 1 year ago

Describe the bug If the application listens for new windows and tries to show a modal dialog on top of them, then this works on MacOS and Windows, but on Linux the modal dialog is shown behind the parent window, but locking the latter, so the application feels frozen. Depending on the location of the shells, the user has no way to bring the modal dialog to front to confirm it.

To Reproduce Please run this snippet

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;

public class DialogBehindWindow {

    public static void main(String[] args) {
        final Display display = new Display();
        final Shell shell = new Shell(display, SWT.SHELL_TRIM);
        shell.setText("My App");
        shell.setLayout(new FillLayout());
        final Text text = new Text(shell, SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
        text.setText("type something");
        final int width = 1100;
        final int height = 700;
        shell.setSize(width, height);
        final Rectangle monitorBounds = display.getPrimaryMonitor().getBounds();
        shell.setLocation(monitorBounds.x + monitorBounds.width / 2 - width /2,
                monitorBounds.y + monitorBounds.height / 2 - height /2);

        shell.addListener(SWT.Show,
                event -> showModalDialog(shell));

        shell.open();

        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }

        display.dispose();
    }

    private static void showModalDialog(Shell parent) {
        final Shell shell = new Shell(parent, SWT.PRIMARY_MODAL | SWT.DIALOG_TRIM);
        shell.setLayout(new GridLayout());
        final Button button = new Button(shell, SWT.PUSH);
        button.setText("Close");
        button.addListener(SWT.Selection, event -> shell.dispose());
        final int width = 400;
        final int height = 200;
        shell.setSize(width, height);
        final Rectangle bounds = parent.getBounds();
        shell.setLocation(bounds.x + bounds.width / 2 - width / 2,
                bounds.y + bounds.height / 2 - height / 2);
        shell.open();
        shell.forceActive();
    }
}

Expected behavior As on Windows or MacOS the modal dialog should be shown in front of the parent shell.

Screenshots Windows 11:

windows11

Latest Manjaro/Gnome manjaro-gnome

Environment:

  1. Select the platform(s) on which the behavior is seen:
      • [ ] All OS
      • [ ] Windows
      • [x] Linux
      • [ ] macOS

Workaround (or) Additional context Delay the dialog showing with display.asyncExec.

Phillipus commented 1 year ago

Wayland or X11?

tmssngr commented 1 year ago

Both. With GDK_BACKEND=x11 it has the advantage that the user can move the large parent window by dragging its title.