Reputation: 93
If I create a javafx dialog using the following method:
public static void showDialog(Event event) throws IOException {
dialogStage = new Stage();
GridPane grid = (GridPane) Start.createLoader().load(Start.class.getResource("file.fxml").openStream());
dialogStage.setScene(new Scene(grid));
dialogStage.setTitle("Title");
dialogStage.initModality(Modality.WINDOW_MODAL);
dialogStage.initOwner(((Node) event.getSource()).getScene().getWindow());
dialogStage.showAndWait();
}
the ower window moves in case it is maximized. This also happens if I use:
Modality.APPLICATION_MODAL
It works if I combine:
dialogStage.initModality(Modality.WINDOW_MODAL);
dialogStage.initOwner(primaryStage.getOwner());
but in this case the owner window is not blocked. I want my dialog showing up on a maximized window without moving it. The maximized window should be blocked while the dialog is open. How can I do this?
Btw. I am using java 8 and javafx on linux.
Tanks!
Upvotes: 4
Views: 830
Reputation: 718
Finally I found another solution that works pretty fine on Linux. It uses a trick: if the user restores the window from the maximized state manually by double clicking on the title, and then maximizes it again by double clicking on the title, this bug is not reproduced anymore. To emulate double clicking I use the Robot:
stage.setMaximized(true);
if (PlatformUtil.isLinux()) { // a workaround of a bug of modal dialogs shown on top of the stage
stage.setAlwaysOnTop(true);
stage.addEventHandler(WindowEvent.WINDOW_SHOWN, new EventHandler<>() {
@Override
public void handle(WindowEvent windowEvent) {
stage.removeEventHandler(WindowEvent.WINDOW_SHOWN, this);
new Thread(() -> {
doubleClick();
LockSupport.parkNanos(10_000_000L);
doubleClick();
Platform.runLater(() -> stage.setAlwaysOnTop(false));
}).start();
}
private void doubleClick() {
robotAction(stage, r -> r.mouseClick(MouseButton.PRIMARY));
LockSupport.parkNanos(1_000_000L);
robotAction(stage, r -> r.mouseClick(MouseButton.PRIMARY));
}
private void robotAction(Stage stage, Consumer<Robot> action) {
var latch = new CountDownLatch(1);
Platform.runLater(() -> {
try {
var robot = new Robot();
var centerX = stage.getX() + stage.getWidth() / 2d;
robot.mouseMove(centerX, stage.getY() + 3d);
action.accept(robot);
} finally {
latch.countDown();
}
});
try {
latch.await();
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
}
});
}
stage.show();
Upvotes: 0
Reputation: 718
As a workaround for Linux it's possible to use this trick:
stage.setMaximized(true);
if (PlatformUtil.isLinux()) {
stage.addEventHandler(WindowEvent.WINDOW_SHOWN, new EventHandler<>() {
@Override
public void handle(WindowEvent windowEvent) {
stage.removeEventHandler(WindowEvent.WINDOW_SHOWN, this);
Platform.runLater(() -> {
var bounds = new Rectangle2D(stage.getX(), stage.getY(), stage.getWidth(), stage.getHeight());
stage.setMaximized(false);
stage.setX(bounds.getMinX());
stage.setY(bounds.getMinY());
stage.setWidth(bounds.getWidth());
stage.setHeight(bounds.getHeight());
stage.setMaximized(true);
});
}
});
}
Upvotes: 0