diff --git a/platform/platform-impl/src/com/intellij/openapi/util/WindowStateServiceImpl.java b/platform/platform-impl/src/com/intellij/openapi/util/WindowStateServiceImpl.java index 86c412c19124..bfa2095d40e5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/util/WindowStateServiceImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/util/WindowStateServiceImpl.java @@ -348,12 +348,53 @@ abstract class WindowStateServiceImpl extends WindowStateService implements Modi T get(@NotNull Class type, @Nullable Rectangle screen) { Point location = apply(Point::new, myLocation); Dimension size = apply(Dimension::new, mySize); - // convert location and size according to the given screen - if (myScreen != null && !myScreen.isEmpty() && screen != null && !screen.isEmpty()) { - if (location != null) ScreenUtil.moveAndScale(location, myScreen, screen); - if (size != null) ScreenUtil.moveAndScale(size, myScreen, screen); - if (!isVisible(location, size)) return null; // adjusted state is not visible + // convert location and size according to the given screen and normalize to fit + if (location != null || size != null) { + if (myScreen != null && !myScreen.isEmpty() && screen != null && !screen.isEmpty()) { + if (location != null) ScreenUtil.moveAndScale(location, myScreen, screen); + if (size != null) ScreenUtil.moveAndScale(size, myScreen, screen); + + if (location != null && size != null) { + Rectangle r = new Rectangle(location, size); + Rectangle original = new Rectangle(r); + ScreenUtil.moveToFit(r, screen.getBounds(), null, true); + if (!r.equals(original)) { + LOG.warn("Window state forced to fit screen: " + original + " -> " + r + " (screen: " + screen + ")"); + } + location = r.getLocation(); + size = r.getSize(); + } + else if (location != null) { + Point original = new Point(location); + if (location.x < screen.x || location.x >= screen.x + screen.width) { + location.x = screen.x + screen.width / 2; + } + if (location.y < screen.y || location.y >= screen.y + screen.height) { + location.y = screen.y + screen.height / 2; + } + if (!location.equals(original)) { + LOG.warn("Window location forced to fit screen: " + original + " -> " + location + " (screen: " + screen + ")"); + } + } + else { + location = new Point(screen.x + screen.width / 2, screen.y + screen.height / 2); + Rectangle r = new Rectangle(location, size); + Dimension original = new Dimension(size); + ScreenUtil.moveToFit(r, screen.getBounds(), null, true); + if (!size.equals(original)) { + LOG.warn("Window size forced to fit screen: " + original + " -> " + size + " (screen: " + screen + ")"); + } + location = r.getLocation(); + size = r.getSize(); + } + + if (!isVisible(location, size)) { + LOG.warn("Adjusted window state is not visible: location=" + location + ", size=" + size + " (screen: " + screen + ")"); + return null; // adjusted state is not visible + } + } } + if (type == Point.class) return (T)location; if (type == Dimension.class) return (T)size; if (type == Rectangle.class) return location == null || size == null ? null : (T)new Rectangle(location, size); diff --git a/platform/util/ui/src/com/intellij/ui/ScreenUtil.java b/platform/util/ui/src/com/intellij/ui/ScreenUtil.java index bbc0fe983830..c5c08aadec5d 100644 --- a/platform/util/ui/src/com/intellij/ui/ScreenUtil.java +++ b/platform/util/ui/src/com/intellij/ui/ScreenUtil.java @@ -1,7 +1,6 @@ // Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.ui; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Pair; import com.intellij.ui.scale.JBUIScale; import com.intellij.util.SystemProperties; @@ -334,13 +333,17 @@ public final class ScreenUtil { } public static void moveRectangleToFitTheScreen(@NotNull Rectangle aRectangle) { + moveRectangleToFitTheScreen(aRectangle, false); + } + + private static void moveRectangleToFitTheScreen(@NotNull Rectangle aRectangle, boolean crop) { if (StartupUiUtil.isWaylandToolkit()) return; // No abs coordinates in Wayland int screenX = aRectangle.x + aRectangle.width / 2; int screenY = aRectangle.y + aRectangle.height / 2; Rectangle screen = getScreenRectangle(screenX, screenY); - moveToFit(aRectangle, screen, null); + moveToFit(aRectangle, screen, null, crop); } public static void moveToFit(final @NotNull Rectangle rectangle, final @NotNull Rectangle container, @Nullable Insets padding) { @@ -421,29 +424,7 @@ public final class ScreenUtil { } public static void fitToScreen(@NotNull Rectangle r) { - if (StartupUiUtil.isWaylandToolkit()) return; // No abs coordinates in Wayland - - Rectangle screen = getScreenRectangle(r.x, r.y); - - int xOverdraft = r.x + r.width - screen.x - screen.width; - if (xOverdraft > 0) { - int shift = Math.min(xOverdraft, r.x - screen.x); - xOverdraft -= shift; - r.x -= shift; - if (xOverdraft > 0) { - r.width -= xOverdraft; - } - } - - int yOverdraft = r.y + r.height - screen.y - screen.height; - if (yOverdraft > 0) { - int shift = Math.min(yOverdraft, r.y - screen.y); - yOverdraft -= shift; - r.y -= shift; - if (yOverdraft > 0) { - r.height -= yOverdraft; - } - } + moveRectangleToFitTheScreen(r, true); } public static @NotNull Point findNearestPointOnBorder(@NotNull Rectangle rect, @NotNull Point p) {