From b2bee992867367b431028c968846d94bd87b351e Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 11 Mar 2025 16:03:49 +0100 Subject: [PATCH] Refactor: Out-of-bounds-check (#3778) fixes #3723, fixes #3722 --- .../ui/mainwindow/MainWindowController.java | 52 +++++++++++++++---- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java b/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java index 13412dd27..18db5e5ac 100644 --- a/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java +++ b/src/main/java/org/cryptomator/ui/mainwindow/MainWindowController.java @@ -19,9 +19,11 @@ import javafx.beans.property.ObjectProperty; import javafx.beans.property.ReadOnlyBooleanProperty; import javafx.beans.property.ReadOnlyObjectProperty; import javafx.fxml.FXML; +import javafx.geometry.Rectangle2D; import javafx.scene.layout.StackPane; import javafx.stage.Screen; import javafx.stage.Stage; +import javafx.stage.WindowEvent; @MainWindowScoped public class MainWindowController implements FxController { @@ -68,18 +70,15 @@ public class MainWindowController implements FxController { int y = settings.windowYPosition.get(); int width = settings.windowWidth.get(); int height = settings.windowHeight.get(); - if (windowPositionSaved(x, y, width, height) ) { - if(isWithinDisplayBounds(x, y, width, height)) { //use stored window position - window.setX(x); - window.setY(y); - window.setWidth(Math.clamp(width, window.getMinWidth(), window.getMaxWidth())); - window.setHeight(Math.clamp(height, window.getMinHeight(), window.getMaxHeight())); - } else if(isWithinDisplayBounds((int) window.getX(), (int) window.getY(), width, height)) { //just reset position of upper left corner, keep window size - window.setWidth(Math.clamp(width, window.getMinWidth(), window.getMaxWidth())); - window.setHeight(Math.clamp(height, window.getMinHeight(), window.getMaxHeight())); - } //else reset window completely + if (windowPositionSaved(x, y, width, height)) { + window.setX(x); + window.setY(y); + window.setWidth(Math.clamp(width, window.getMinWidth(), window.getMaxWidth())); + window.setHeight(Math.clamp(height, window.getMinHeight(), window.getMaxHeight())); } + window.setOnShowing(this::checkDisplayBounds); + settings.windowXPosition.bind(window.xProperty()); settings.windowYPosition.bind(window.yProperty()); settings.windowWidth.bind(window.widthProperty()); @@ -90,6 +89,39 @@ public class MainWindowController implements FxController { return x != 0 || y != 0 || width != 0 || height != 0; } + private void checkDisplayBounds(WindowEvent windowEvent) { + int x = settings.windowXPosition.get(); + int y = settings.windowYPosition.get(); + int width = settings.windowWidth.get(); + int height = settings.windowHeight.get(); + + // Minimizing a window in Windows and closing it could result in an out of bounds position at (x, y) = (-32000, -32000) + // See https://devblogs.microsoft.com/oldnewthing/20041028-00/?p=37453 + // If the position is (-32000, -32000), restore to the last saved position + if (window.getX() == -32000 && window.getY() == -32000) { + window.setX(x); + window.setY(y); + window.setWidth(width); + window.setHeight(height); + } + + Rectangle2D primaryScreenBounds = Screen.getPrimary().getBounds(); + if (!isWithinDisplayBounds(x, y, width, height)) { //use stored window position + LOG.debug("Resetting window position due to insufficient screen overlap"); + var centeredX = (primaryScreenBounds.getWidth() - window.getMinWidth()) / 2; + var centeredY = (primaryScreenBounds.getHeight() - window.getMinHeight()) / 2; + //check if we can keep width and height + if (isWithinDisplayBounds((int) centeredX, (int) centeredY, width, height)) { + //if so, keep window size + window.setWidth(Math.clamp(width, window.getMinWidth(), window.getMaxWidth())); + window.setHeight(Math.clamp(height, window.getMinHeight(), window.getMaxHeight())); + } + //reset position of upper left corner + window.setX(centeredX); + window.setY(centeredY); + } + } + private boolean isWithinDisplayBounds(int x, int y, int width, int height) { // define a rect which is inset on all sides from the window's rect: final int shrinkedX = x + 20; // 20px left