diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 357b2e3e4..e15900880 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -8,7 +8,7 @@ updates:
time: "06:00"
timezone: "UTC"
groups:
- all: # one PR for all dependencies
+ maven-dependencies:
patterns:
- "*"
@@ -17,7 +17,7 @@ updates:
schedule:
interval: "monthly"
groups:
- all: # one PR for all actions
+ github-actions:
patterns:
- "*"
labels:
diff --git a/dist/mac/resources/Cryptomator.icns b/dist/mac/resources/Cryptomator.icns
index 25da5b5be..79f5fdb39 100644
Binary files a/dist/mac/resources/Cryptomator.icns and b/dist/mac/resources/Cryptomator.icns differ
diff --git a/pom.xml b/pom.xml
index d5c3d3f33..322dcfb36 100644
--- a/pom.xml
+++ b/pom.xml
@@ -54,16 +54,16 @@
1.4.11
2.0.7
0.6.0
- 1.8.0
+ 1.8.2
5.10.0
- 5.4.0
+ 5.5.0
2.2
24.0.1
- 8.3.1
+ 8.4.0
0.8.10
2.2.0
1.2.1
diff --git a/src/main/java/org/cryptomator/common/settings/Settings.java b/src/main/java/org/cryptomator/common/settings/Settings.java
index fd9f01904..4e0e0df97 100644
--- a/src/main/java/org/cryptomator/common/settings/Settings.java
+++ b/src/main/java/org/cryptomator/common/settings/Settings.java
@@ -65,7 +65,6 @@ public class Settings {
public final IntegerProperty windowYPosition;
public final IntegerProperty windowWidth;
public final IntegerProperty windowHeight;
- public final StringProperty displayConfiguration;
public final StringProperty language;
public final StringProperty mountService;
public final StringProperty lastUpdateCheck;
@@ -103,7 +102,6 @@ public class Settings {
this.windowYPosition = new SimpleIntegerProperty(this, "windowYPosition", json.windowYPosition);
this.windowWidth = new SimpleIntegerProperty(this, "windowWidth", json.windowWidth);
this.windowHeight = new SimpleIntegerProperty(this, "windowHeight", json.windowHeight);
- this.displayConfiguration = new SimpleStringProperty(this, "displayConfiguration", json.displayConfiguration);
this.language = new SimpleStringProperty(this, "language", json.language);
this.mountService = new SimpleStringProperty(this, "mountService", json.mountService);
this.lastUpdateCheck = new SimpleStringProperty(this, "lastUpdateCheck", json.lastUpdateCheck);
@@ -131,7 +129,6 @@ public class Settings {
windowYPosition.addListener(this::somethingChanged);
windowWidth.addListener(this::somethingChanged);
windowHeight.addListener(this::somethingChanged);
- displayConfiguration.addListener(this::somethingChanged);
language.addListener(this::somethingChanged);
mountService.addListener(this::somethingChanged);
lastUpdateCheck.addListener(this::somethingChanged);
@@ -186,7 +183,6 @@ public class Settings {
json.windowYPosition = windowYPosition.get();
json.windowWidth = windowWidth.get();
json.windowHeight = windowHeight.get();
- json.displayConfiguration = displayConfiguration.get();
json.language = language.get();
json.mountService = mountService.get();
json.lastUpdateCheck = lastUpdateCheck.get();
diff --git a/src/main/java/org/cryptomator/common/settings/SettingsJson.java b/src/main/java/org/cryptomator/common/settings/SettingsJson.java
index 977e1d3cd..2c7c963da 100644
--- a/src/main/java/org/cryptomator/common/settings/SettingsJson.java
+++ b/src/main/java/org/cryptomator/common/settings/SettingsJson.java
@@ -31,9 +31,6 @@ class SettingsJson {
@JsonProperty("theme")
UiTheme theme = Settings.DEFAULT_THEME;
- @JsonProperty("displayConfiguration")
- String displayConfiguration;
-
@JsonProperty("keychainProvider")
String keychainProvider = Settings.DEFAULT_KEYCHAIN_PROVIDER;
diff --git a/src/main/java/org/cryptomator/ui/mainwindow/ResizeController.java b/src/main/java/org/cryptomator/ui/mainwindow/ResizeController.java
index 1b3f1b69f..b136fa55c 100644
--- a/src/main/java/org/cryptomator/ui/mainwindow/ResizeController.java
+++ b/src/main/java/org/cryptomator/ui/mainwindow/ResizeController.java
@@ -6,7 +6,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
-import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
@@ -15,6 +14,7 @@ import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Region;
import javafx.stage.Screen;
import javafx.stage.Stage;
+import javafx.stage.WindowEvent;
@MainWindow
public class ResizeController implements FxController {
@@ -53,48 +53,70 @@ public class ResizeController implements FxController {
public void initialize() {
LOG.trace("init ResizeController");
- if (neverTouched()) {
- settings.displayConfiguration.set(getMonitorSizes());
- return;
- } else {
- if (didDisplayConfigurationChange()) {
- //If the position is illegal, then the window appears on the main screen in the middle of the window.
- Rectangle2D primaryScreenBounds = Screen.getPrimary().getBounds();
- window.setX((primaryScreenBounds.getWidth() - window.getMinWidth()) / 2);
- window.setY((primaryScreenBounds.getHeight() - window.getMinHeight()) / 2);
- window.setWidth(window.getMinWidth());
- window.setHeight(window.getMinHeight());
- } else {
- window.setHeight(settings.windowHeight.get() > window.getMinHeight() ? settings.windowHeight.get() : window.getMinHeight());
- window.setWidth(settings.windowWidth.get() > window.getMinWidth() ? settings.windowWidth.get() : window.getMinWidth());
- window.setX(settings.windowXPosition.get());
- window.setY(settings.windowYPosition.get());
- }
+ if (!neverTouched()) {
+ window.setHeight(settings.windowHeight.get() > window.getMinHeight() ? settings.windowHeight.get() : window.getMinHeight());
+ window.setWidth(settings.windowWidth.get() > window.getMinWidth() ? settings.windowWidth.get() : window.getMinWidth());
+ window.setX(settings.windowXPosition.get());
+ window.setY(settings.windowYPosition.get());
}
- savePositionalSettings();
+
+ window.setOnShowing(this::checkDisplayBounds);
}
private boolean neverTouched() {
return (settings.windowHeight.get() == 0) && (settings.windowWidth.get() == 0) && (settings.windowXPosition.get() == 0) && (settings.windowYPosition.get() == 0);
}
- private boolean didDisplayConfigurationChange() {
- String currentDisplayConfiguration = getMonitorSizes();
- String settingsDisplayConfiguration = settings.displayConfiguration.get();
- boolean configurationHasChanged = !settingsDisplayConfiguration.equals(currentDisplayConfiguration);
- if (configurationHasChanged) settings.displayConfiguration.set(currentDisplayConfiguration);
- return configurationHasChanged;
+ private boolean isWithinDisplayBounds() {
+ // (x1, y1) is the top left corner of the window, (x2, y2) is the bottom right corner
+ final double slack = 10;
+ final double width = window.getWidth() - 2 * slack;
+ final double height = window.getHeight() - 2 * slack;
+ final double x1 = window.getX() + slack;
+ final double y1 = window.getY() + slack;
+ final double x2 = x1 + width;
+ final double y2 = y1 + height;
+
+ final ObservableList screens = Screen.getScreensForRectangle(x1, y1, width, height);
+
+ // Find the total visible area of the window
+ double visibleArea = 0;
+ for (Screen screen : screens) {
+ Rectangle2D bounds = screen.getVisualBounds();
+
+ double xOverlap = Math.min(x2, bounds.getMaxX()) - Math.max(x1, bounds.getMinX());
+ double yOverlap = Math.min(y2, bounds.getMaxY()) - Math.max(y1, bounds.getMinY());
+
+ visibleArea += xOverlap * yOverlap;
+ }
+
+ final double windowArea = width * height;
+
+ // Within bounds if the visible area matches the window area
+ return visibleArea == windowArea;
}
- private String getMonitorSizes() {
- ObservableList screens = Screen.getScreens();
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < screens.size(); i++) {
- Rectangle2D screenBounds = screens.get(i).getBounds();
- if (!sb.isEmpty()) sb.append(" ");
- sb.append("displayId: " + i + ", " + screenBounds.getWidth() + "x" + screenBounds.getHeight() + ";");
+ private void checkDisplayBounds(WindowEvent evt) {
+
+ // 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(settings.windowXPosition.get());
+ window.setY(settings.windowYPosition.get());
+ window.setWidth(settings.windowWidth.get());
+ window.setHeight(settings.windowHeight.get());
+ }
+
+ if (!isWithinDisplayBounds()) {
+ // If the position is illegal, then the window appears on the main screen in the middle of the window.
+ Rectangle2D primaryScreenBounds = Screen.getPrimary().getBounds();
+ window.setX((primaryScreenBounds.getWidth() - window.getMinWidth()) / 2);
+ window.setY((primaryScreenBounds.getHeight() - window.getMinHeight()) / 2);
+ window.setWidth(window.getMinWidth());
+ window.setHeight(window.getMinHeight());
+ savePositionalSettings();
}
- return sb.toString();
}
private void startResize(MouseEvent evt) {
@@ -183,5 +205,4 @@ public class ResizeController implements FxController {
public boolean isShowResizingArrows() {
return showResizingArrows.get();
}
-
}
\ No newline at end of file