From 983b271d29b0a7f6036f3dff73127d6fe40f481d Mon Sep 17 00:00:00 2001 From: Amartya Parijat Date: Wed, 8 Jan 2025 14:53:02 +0100 Subject: [PATCH] Use MonitorAware Coordinates in multi zoom This commit contributes to the use of MonitorAware points and rectangles in the multi zoom coordinate system mapper for translation between points and pixels. contributes to #62 and #127 --- .../widgets/CoordinateSystemMapperTests.java | 103 +++++++++---- .../swt/graphics/MonitorAwarePoint.java | 54 +++++++ .../swt/graphics/MonitorAwareRectangle.java | 56 +++++++ .../org/eclipse/swt/graphics/Point.java | 2 +- .../org/eclipse/swt/graphics/Rectangle.java | 2 +- .../MultiZoomCoordinateSystemMapper.java | 138 ++++++++++-------- .../win32/org/eclipse/swt/widgets/Shell.java | 3 +- 7 files changed, 266 insertions(+), 92 deletions(-) create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/MonitorAwarePoint.java create mode 100644 bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/MonitorAwareRectangle.java diff --git a/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/widgets/CoordinateSystemMapperTests.java b/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/widgets/CoordinateSystemMapperTests.java index 75101e16228..4f80725caf7 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/widgets/CoordinateSystemMapperTests.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/widgets/CoordinateSystemMapperTests.java @@ -13,6 +13,7 @@ *******************************************************************************/ package org.eclipse.swt.widgets; +import static org.junit.Assert.assertTrue; import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.function.*; @@ -39,16 +40,24 @@ private Monitor createMonitor(CoordinateSystemMapper mapper, Rectangle boundsInP return monitor; } - void setupMonitors(CoordinateSystemMapper mapper) { + private void setupMonitors(CoordinateSystemMapper mapper) { Rectangle boundsInPixelsForLeftMonitor = new Rectangle(0, 0, 2000, 2000); Rectangle boundsInPixelsForRightMonitor = new Rectangle(2000, 0, 2000, 2000); monitors = new Monitor[] { createMonitor(mapper, boundsInPixelsForLeftMonitor, 200), createMonitor(mapper, boundsInPixelsForRightMonitor, 100) }; } - Stream provideCoordinateSystemMappers() { - return Stream.of(new MultiZoomCoordinateSystemMapper(null, () -> monitors), - new SingleZoomCoordinateSystemMapper(null)); + private Stream provideCoordinateSystemMappers() { + return Stream.of(getMultiZoomCoordinateSystemMapper(), + getSingleZoomCoordinateSystemMapper()); + } + + private MultiZoomCoordinateSystemMapper getMultiZoomCoordinateSystemMapper() { + return new MultiZoomCoordinateSystemMapper(null, () -> monitors); + } + + private SingleZoomCoordinateSystemMapper getSingleZoomCoordinateSystemMapper() { + return new SingleZoomCoordinateSystemMapper(null); } @ParameterizedTest @@ -60,16 +69,27 @@ void translatePointInNoMonitorBackAndForthShouldBeTheSame(CoordinateSystemMapper assertEquals(pt, mapper.translateFromDisplayCoordinates(px, monitors[0].getZoom())); } - @ParameterizedTest - @MethodSource("provideCoordinateSystemMappers") - @Disabled("Disabled due to current limitations of MultiZoomCoordinateSystemMapper") - void translatePointInGapBackAndForthShouldBeTheSame(CoordinateSystemMapper mapper) { + @Test + void translatePointInGapBackAndForthInSingleZoomShouldBeTheSame() { + SingleZoomCoordinateSystemMapper mapper = getSingleZoomCoordinateSystemMapper(); setupMonitors(mapper); Point pt = new Point(1900, 400); Point px = mapper.translateToDisplayCoordinates(pt, monitors[0].getZoom()); assertEquals(pt, mapper.translateFromDisplayCoordinates(px, monitors[0].getZoom())); } + @Test + void translatePointInGapBackAndForthInMultiZoomShouldEndInsideTheSameMonitor() { + MultiZoomCoordinateSystemMapper mapper = getMultiZoomCoordinateSystemMapper(); + setupMonitors(mapper); + Point pt = new Point(1900, 400); + Point px = mapper.translateToDisplayCoordinates(pt, monitors[0].getZoom()); + Point translatedPt = mapper.translateFromDisplayCoordinates(px, monitors[0].getZoom()); + Point translatedPx = mapper.translateToDisplayCoordinates(translatedPt, monitors[0].getZoom()); + assertEquals(translatedPt, translatedPx); + assertEquals(translatedPx, px); + } + @ParameterizedTest @MethodSource("provideCoordinateSystemMappers") void translateRectangleInNoMonitorBackAndForthShouldBeTheSame(CoordinateSystemMapper mapper) { @@ -79,22 +99,46 @@ void translateRectangleInNoMonitorBackAndForthShouldBeTheSame(CoordinateSystemMa assertEquals(rectInPts, mapper.translateFromDisplayCoordinates(rectInPxs, monitors[0].getZoom())); } - @ParameterizedTest - @MethodSource("provideCoordinateSystemMappers") - @Disabled("Disabled due to current limitations of MultiZoomCoordinateSystemMapper") - void translateRectangleInGapBackAndForthShouldBeTheSame(CoordinateSystemMapper mapper) { + @Test + void translateRectangleInGapBackAndForthInSingleZoomShouldBeTheSame() { + SingleZoomCoordinateSystemMapper mapper = getSingleZoomCoordinateSystemMapper(); setupMonitors(mapper); Rectangle rectInPts = new Rectangle(1800, 400, 100, 100); Rectangle rectInPxs = mapper.translateToDisplayCoordinates(rectInPts, monitors[0].getZoom()); assertEquals(rectInPts, mapper.translateFromDisplayCoordinates(rectInPxs, monitors[0].getZoom())); } - @ParameterizedTest - @MethodSource("provideCoordinateSystemMappers") - @Disabled("Disabled due to current limitations of MultiZoomCoordinateSystemMapper") - void translateRectangleInGapPartiallyInRightBackAndForthShouldBeTheSame(CoordinateSystemMapper mapper) { + @Test + void translateRectangleInGapBackAndForthInMultiZoomShouldBeInMonitorBounds() { + MultiZoomCoordinateSystemMapper mapper = getMultiZoomCoordinateSystemMapper(); setupMonitors(mapper); - Rectangle rectInPts = new Rectangle(1950, 400, 100, 100); + Rectangle rectInPts = new Rectangle(1800, 400, 100, 100); + Rectangle rectInPxs = mapper.translateToDisplayCoordinates(rectInPts, monitors[0].getZoom()); + Rectangle rectInPtsTranslated = mapper.translateFromDisplayCoordinates(rectInPxs, monitors[0].getZoom()); + boolean isInsideMonitor = false; + for (Monitor monitor : monitors) { + if (monitor.getClientArea().intersects(rectInPtsTranslated)) { + isInsideMonitor = true; + break; + } + } + assertTrue("The translated rectangle in points is inside the monitor bounds in points", isInsideMonitor); + } + + @Test + void translateRectangleInGapPartiallyInRightBackAndForthInSingleZoomShouldBeTheSame() { + SingleZoomCoordinateSystemMapper mapper = getSingleZoomCoordinateSystemMapper(); + setupMonitors(mapper); + Rectangle rectInPts = new Rectangle(1950, 400, 150, 100); + Rectangle rectInPxs = mapper.translateToDisplayCoordinates(rectInPts, monitors[0].getZoom()); + assertEquals(rectInPts, mapper.translateFromDisplayCoordinates(rectInPxs, monitors[0].getZoom())); + } + + @Test + void translateRectangleInGapPartiallyInRightBackAndForthInMultiZoomShouldBeInside() { + MultiZoomCoordinateSystemMapper mapper = getMultiZoomCoordinateSystemMapper(); + setupMonitors(mapper); + Rectangle rectInPts = new MonitorAwareRectangle(1950, 400, 150, 100, monitors[1]); Rectangle rectInPxs = mapper.translateToDisplayCoordinates(rectInPts, monitors[0].getZoom()); assertEquals(rectInPts, mapper.translateFromDisplayCoordinates(rectInPxs, monitors[0].getZoom())); } @@ -108,9 +152,9 @@ void translateRectangleInGapPartiallyInLeftBackAndForthShouldBeTheSame(Coordinat assertEquals(rectInPts, mapper.translateFromDisplayCoordinates(rectInPxs, monitors[0].getZoom())); } - @ParameterizedTest - @MethodSource("provideCoordinateSystemMappers") - void translateRectangleInPointsInBothMonitorsPartiallyBackAndForthShouldBeTheSame(CoordinateSystemMapper mapper) { + @Test + void translateRectangleInPointsInBothMonitorsPartiallyBackAndForthInSingleZoomShouldBeTheSame() { + SingleZoomCoordinateSystemMapper mapper = getSingleZoomCoordinateSystemMapper(); setupMonitors(mapper); Rectangle rectInPts = new Rectangle(950, 400, 1500, 100); Rectangle rectInPxs = mapper.translateToDisplayCoordinates(rectInPts, monitors[0].getZoom()); @@ -118,9 +162,19 @@ void translateRectangleInPointsInBothMonitorsPartiallyBackAndForthShouldBeTheSam } @Test - @Disabled("Disabled due to current limitations of MultiZoomCoordinateSystemMapper") + void translateRectangleInPointsInBothMonitorsPartiallyBackAndForthInMultiZoomShouldNotEndUpInGap() { + MultiZoomCoordinateSystemMapper mapper = getMultiZoomCoordinateSystemMapper(); + setupMonitors(mapper); + Rectangle rectInPts = new Rectangle(950, 400, 1500, 100); + Rectangle rectInPxs = mapper.translateToDisplayCoordinates(rectInPts, monitors[0].getZoom()); + Rectangle rectInPtsTranslated = mapper.translateFromDisplayCoordinates(rectInPxs, monitors[0].getZoom()); + Rectangle rectInPxsTranslated = mapper.translateToDisplayCoordinates(rectInPtsTranslated, monitors[0].getZoom()); + assertEquals(rectInPxs, rectInPxsTranslated); + } + + @Test void moveRectangleInPixelsInRightMonitorsPartiallyBackAndForthShouldBeTheSame() { - CoordinateSystemMapper mapper = provideCoordinateSystemMappers().findFirst().get(); + MultiZoomCoordinateSystemMapper mapper = getMultiZoomCoordinateSystemMapper(); setupMonitors(mapper); Rectangle rectInPxs = new Rectangle(1990, -10, 2000, 2000); Rectangle expectedSmallRectInPxs = new Rectangle(0, 0, 0, monitors[0].getZoom()); @@ -139,11 +193,10 @@ void moveRectangleInPixelsInRightMonitorsPartiallyBackAndForthShouldBeTheSame() } @ParameterizedTest - @MethodSource("provideCoordinateSystemMappers") - @Disabled("Disabled due to current limitations of MultiZoomCoordinateSystemMapper") + @MethodSource("provideCoordinateSystemMappers") void translateRectangleInPixelsOutisdeMonitorsBackAndForthShouldBeTheSame(CoordinateSystemMapper mapper) { setupMonitors(mapper); - Rectangle rectInPxs = new Rectangle(4400, 400, 1000, 1000); + Rectangle rectInPxs = new Rectangle(400, 2400, 1000, 1000); Rectangle rectInPts = mapper.translateFromDisplayCoordinates(rectInPxs, monitors[0].getZoom()); assertEquals(rectInPxs, mapper.translateToDisplayCoordinates(rectInPts, monitors[0].getZoom())); } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/MonitorAwarePoint.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/MonitorAwarePoint.java new file mode 100644 index 00000000000..b667d0629c5 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/MonitorAwarePoint.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2025 Yatta Solutions and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Yatta Solutions - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.graphics; + +import org.eclipse.swt.widgets.*; + +/** + * Instances of this class represent {@link org.eclipse.swt.graphics.Point} + * objects along with the context of the monitor in relation to which they are + * placed on the display. The monitor awareness makes it easy to scale and + * translate the points between pixels and points + * + * @since 3.129 + */ +public final class MonitorAwarePoint extends Point { + + private static final long serialVersionUID = 6077427420686999194L; + + /** + * Constructs a new MonitorAwarePoint + * + * @param x the x coordinate of the point + * @param y the y coordinate of the point + * @param monitor the monitor with whose context the point is created + * + * @since 3.129 + */ + public MonitorAwarePoint(int x, int y, Monitor monitor) { + super(x, y); + this.monitor = monitor; + } + + /** + * Gets the monitor with whose context the instance is created + * + * @since 3.129 + */ + public Monitor getMonitor() { + return monitor; + } + + private final Monitor monitor; +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/MonitorAwareRectangle.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/MonitorAwareRectangle.java new file mode 100644 index 00000000000..6c3cc18aeb3 --- /dev/null +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/MonitorAwareRectangle.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * Copyright (c) 2025 Yatta Solutions and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Yatta Solutions - initial API and implementation + *******************************************************************************/ +package org.eclipse.swt.graphics; + +import org.eclipse.swt.widgets.*; + +/** + * Instances of this class represent {@link org.eclipse.swt.graphics.Rectangle} + * objects along with the context of the monitor in relation to which they are + * placed on the display. The monitor awareness makes it easy to scale and + * translate the rectangles between pixels and points + * + * @since 3.129 + */ +public final class MonitorAwareRectangle extends Rectangle { + + private static final long serialVersionUID = 5041911840525116925L; + + /** + * Constructs a new MonitorAwareRectangle + * + * @param x the x coordinate of the top left corner of the rectangle + * @param y the y coordinate of the top left corner of the rectangle + * @param width the width of the rectangle + * @param height the height of the rectangle + * @param monitor the monitor with whose context the rectangle is created + * + * @since 3.129 + */ + public MonitorAwareRectangle(int x, int y, int width, int height, Monitor monitor) { + super(x, y, width, height); + this.monitor = monitor; + } + + /** + * Gets the monitor with whose context the instance is created + * + * @since 3.129 + */ + public Monitor getMonitor() { + return monitor; + } + + private final Monitor monitor; +} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Point.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Point.java index 069fb4d81eb..04e45f681fe 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Point.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Point.java @@ -41,7 +41,7 @@ * @see Sample code and further information */ -public final class Point implements Serializable { +public sealed class Point implements Serializable permits MonitorAwarePoint { /** * the x coordinate of the point diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Rectangle.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Rectangle.java index f15babb2ba9..c6dc284e1bd 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Rectangle.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Rectangle.java @@ -45,7 +45,7 @@ * @see Sample code and further information */ -public final class Rectangle implements Serializable { +public sealed class Rectangle implements Serializable permits MonitorAwareRectangle { /** * the x coordinate of the rectangle diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/MultiZoomCoordinateSystemMapper.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/MultiZoomCoordinateSystemMapper.java index 7c3d8760ceb..0c73a2318a5 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/MultiZoomCoordinateSystemMapper.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/MultiZoomCoordinateSystemMapper.java @@ -66,13 +66,13 @@ public Rectangle map(Control from, Control to, int x, int y, int width, int heig Rectangle mappedRectangleInPoints; if (from == null) { Rectangle mappedRectangleInPixels = display.mapInPixels(from, to, - translateRectangleInPixelsInDisplayCoordinateSystem(x, y, width, height, + translateRectangleInPointsToPixels(x, y, width, height, to.getShell().getMonitor())); mappedRectangleInPoints = DPIUtil.scaleDown(mappedRectangleInPixels, to.getZoom()); } else if (to == null) { Rectangle mappedRectangleInPixels = display.mapInPixels(from, to, DPIUtil.scaleUp(new Rectangle(x, y, width, height), from.getZoom())); - mappedRectangleInPoints = translateRectangleInPointsInDisplayCoordinateSystem(mappedRectangleInPixels.x, + mappedRectangleInPoints = translateRectangleInPixelsToPoints(mappedRectangleInPixels.x, mappedRectangleInPixels.y, mappedRectangleInPixels.width, mappedRectangleInPixels.height, from.getShell().getMonitor()); } else { @@ -93,94 +93,94 @@ public Rectangle mapMonitorBounds(Rectangle rect, int zoom) { @Override public Point translateFromDisplayCoordinates(Point point, int zoom) { - return translateLocationInPixelsFromDisplayCoordinateSystem(point.x, point.y); + return translateLocationInPixelsToPoints(point.x, point.y); } @Override public Point translateToDisplayCoordinates(Point point, int zoom) { - return translateLocationInPointsToDisplayCoordinateSystem(point.x, point.y); + Monitor monitor = point instanceof MonitorAwarePoint monitorAwarePoint ? monitorAwarePoint.getMonitor() : null; + return translateLocationInPointsToPixels(point.x, point.y, monitor); } @Override public Rectangle translateFromDisplayCoordinates(Rectangle rect, int zoom) { - return translateRectangleInPixelsFromDisplayCoordinateSystemByContainment(rect.x, rect.y, rect.width, - rect.height); + Monitor monitor = rect instanceof MonitorAwareRectangle monitorAwareRect ? monitorAwareRect.getMonitor() : null; + return translateRectangleInPixelsToPoints(rect.x, rect.y, rect.width, rect.height, monitor); } @Override public Rectangle translateToDisplayCoordinates(Rectangle rect, int zoom) { - return translateRectangleInPointsToDisplayCoordinateSystemByContainment(rect.x, rect.y, rect.width, - rect.height); + Monitor monitor = rect instanceof MonitorAwareRectangle monitorAwareRect ? monitorAwareRect.getMonitor() : null; + return translateRectangleInPointsToPixels(rect.x, rect.y, rect.width, rect.height, monitor); } @Override public Point getCursorLocation() { Point cursorLocationInPixels = display.getCursorLocationInPixels(); - return translateLocationInPixelsFromDisplayCoordinateSystem(cursorLocationInPixels.x, cursorLocationInPixels.y); + return translateLocationInPixelsToPoints(cursorLocationInPixels.x, cursorLocationInPixels.y); } @Override - public void setCursorLocation(int x, int y) { - Point cursorLocationInPixels = translateLocationInPointsToDisplayCoordinateSystem(x, y); - display.setCursorLocationInPixels(cursorLocationInPixels.x, cursorLocationInPixels.y); + public void setCursorLocation (int x, int y) { + Point cursorLocationInPixels = translateLocationInPointsToPixels(x, y, null); + display.setCursorLocationInPixels (cursorLocationInPixels.x, cursorLocationInPixels.y); } - private Point translateLocationInPointsToDisplayCoordinateSystem(int x, int y) { - Monitor monitor = getContainingMonitor(x, y); + private Point translateLocationInPointsToPixels(int x, int y, Monitor monitor) { + monitor = getValidMonitorIfApplicable(x, y, monitor); return getPixelsFromPoint(monitor, x, y); } - private Point translateLocationInPixelsFromDisplayCoordinateSystem(int x, int y) { - Monitor monitor = getContainingMonitorInPixelsCoordinate(x, y); + private Point translateLocationInPixelsToPoints(int x, int y) { + Monitor monitor = getContainingMonitorForPixels(x, y); return getPointFromPixels(monitor, x, y); } - private Rectangle translateRectangleInPointsToDisplayCoordinateSystemByContainment(int x, int y, int width, - int height) { - Monitor monitorByLocation = getContainingMonitor(x, y); - Monitor monitorByContainment = getContainingMonitor(x, y, width, height); - return translateRectangleInPixelsInDisplayCoordinateSystem(x, y, width, height, monitorByLocation, - monitorByContainment); - } - - private Rectangle translateRectangleInPixelsInDisplayCoordinateSystem(int x, int y, int width, int height, - Monitor monitor) { - return translateRectangleInPixelsInDisplayCoordinateSystem(x, y, width, height, monitor, monitor); - } - - private Rectangle translateRectangleInPixelsInDisplayCoordinateSystem(int x, int y, int width, int height, - Monitor monitorOfLocation, Monitor monitorOfArea) { - Point topLeft = getPixelsFromPoint(monitorOfLocation, x, y); - int zoom = getApplicableMonitorZoom(monitorOfArea); + private Rectangle translateRectangleInPointsToPixels(int x, int y, int width, int height, Monitor monitor) { + monitor = getValidMonitorIfApplicable(x, y, width, height, monitor); + Point topLeft = getPixelsFromPoint(monitor, x, y); + int zoom = getApplicableMonitorZoom(monitor); int widthInPixels = DPIUtil.scaleUp(width, zoom); int heightInPixels = DPIUtil.scaleUp(height, zoom); return new Rectangle(topLeft.x, topLeft.y, widthInPixels, heightInPixels); } - private Rectangle translateRectangleInPixelsFromDisplayCoordinateSystemByContainment(int x, int y, - int widthInPixels, int heightInPixels) { - Monitor monitorByLocation = getContainingMonitor(x, y); - Monitor monitorByContainment = getContainingMonitorInPixelsCoordinate(x, y, widthInPixels, heightInPixels); - return translateRectangleInPointsInDisplayCoordinateSystem(x, y, widthInPixels, heightInPixels, - monitorByLocation, monitorByContainment); + private Rectangle translateRectangleInPixelsToPoints(int x, int y, int widthInPixels, int heightInPixels, Monitor monitor) { + if (monitor == null) + monitor = getContainingMonitorForPixels(x, y, widthInPixels, heightInPixels); + int zoom = getApplicableMonitorZoom(monitor); + Point topLeft = getPointFromPixels(monitor, x, y); + int width = DPIUtil.scaleDown(widthInPixels, zoom); + int height = DPIUtil.scaleDown(heightInPixels, zoom); + MonitorAwareRectangle rect = new MonitorAwareRectangle(topLeft.x, topLeft.y, width, height, monitor); + return rect; } - private Rectangle translateRectangleInPointsInDisplayCoordinateSystem(int x, int y, int widthInPixels, - int heightInPixels, Monitor monitor) { - return translateRectangleInPointsInDisplayCoordinateSystem(x, y, widthInPixels, heightInPixels, monitor, - monitor); + private Monitor getValidMonitorIfApplicable(int x, int y, int width, int height, Monitor monitor) { + if(monitor != null) { + if (monitor.getClientArea().intersects(x, y, width, height)) { + return monitor; + } + Monitor containingMonitor = getContainingMonitorForPoints(x, y, width, height); + return containingMonitor != null ? containingMonitor : monitor; + } + Monitor containingMonitor = getContainingMonitorForPoints(x, y, width, height); + return containingMonitor != null ? containingMonitor : monitorSupplier.get()[0]; } - private Rectangle translateRectangleInPointsInDisplayCoordinateSystem(int x, int y, int widthInPixels, - int heightInPixels, Monitor monitorOfLocation, Monitor monitorOfArea) { - Point topLeft = getPointFromPixels(monitorOfLocation, x, y); - int zoom = getApplicableMonitorZoom(monitorOfArea); - int width = DPIUtil.scaleDown(widthInPixels, zoom); - int height = DPIUtil.scaleDown(heightInPixels, zoom); - return new Rectangle(topLeft.x, topLeft.y, width, height); + private Monitor getValidMonitorIfApplicable(int x, int y, Monitor monitor) { + if (monitor != null) { + if (monitor.getClientArea().contains(x, y)) { + return monitor; + } + Monitor containingMonitor = getContainingMonitorForPoints(x, y); + return containingMonitor != null ? containingMonitor : monitor; + } + Monitor containingMonitor = getContainingMonitorForPoints(x, y); + return containingMonitor != null ? containingMonitor : monitorSupplier.get()[0]; } - private Monitor getContainingMonitor(int x, int y) { + private Monitor getContainingMonitorForPoints(int x, int y) { Monitor[] monitors = monitorSupplier.get(); for (Monitor currentMonitor : monitors) { Rectangle clientArea = currentMonitor.getClientArea(); @@ -188,27 +188,33 @@ private Monitor getContainingMonitor(int x, int y) { return currentMonitor; } } - return monitors[0]; + return null; } - private Monitor getContainingMonitor(int x, int y, int width, int height) { - Rectangle rectangle = new Rectangle(x, y, width, height); + private Monitor getContainingMonitorForPoints(int x, int y, int width, int height) { Monitor[] monitors = monitorSupplier.get(); - Monitor selectedMonitor = monitors[0]; - int highestArea = 0; + Monitor selectedMonitor = null; + int highestIntersectionRatio = 0; for (Monitor currentMonitor : monitors) { - Rectangle clientArea = currentMonitor.getClientArea(); - Rectangle intersection = clientArea.intersection(rectangle); - int area = intersection.width * intersection.height; - if (area > highestArea) { + // Obtain the rectangle in pixels per monitor for absolute comparison + Point topLeftOfRectangle = getPixelsFromPoint(currentMonitor, x, y); + int widthInPixels = DPIUtil.scaleUp(width, getApplicableMonitorZoom(currentMonitor)); + int heightInPixels = DPIUtil.scaleUp(height, getApplicableMonitorZoom(currentMonitor)); + Rectangle boundsInPixel = new Rectangle(topLeftOfRectangle.x, topLeftOfRectangle.y, widthInPixels, heightInPixels); + Rectangle clientArea = getMonitorClientAreaInPixels(currentMonitor); + Rectangle intersection = clientArea.intersection(boundsInPixel); + int intersectionArea = intersection.width * intersection.height; + int boundsArea = boundsInPixel.width * boundsInPixel.height; + int intersectionRatio = (intersectionArea * 100) / boundsArea; + if (intersectionRatio > highestIntersectionRatio) { selectedMonitor = currentMonitor; - highestArea = area; + highestIntersectionRatio = intersectionRatio; } } return selectedMonitor; } - private Monitor getContainingMonitorInPixelsCoordinate(int xInPixels, int yInPixels) { + private Monitor getContainingMonitorForPixels(int xInPixels, int yInPixels) { Monitor[] monitors = monitorSupplier.get(); for (Monitor current : monitors) { Rectangle clientArea = getMonitorClientAreaInPixels(current); @@ -219,7 +225,7 @@ private Monitor getContainingMonitorInPixelsCoordinate(int xInPixels, int yInPix return monitors[0]; } - private Monitor getContainingMonitorInPixelsCoordinate(int xInPixels, int yInPixels, int widthInPixels, + private Monitor getContainingMonitorForPixels(int xInPixels, int yInPixels, int widthInPixels, int heightInPixels) { Rectangle rectangle = new Rectangle(xInPixels, yInPixels, widthInPixels, heightInPixels); Monitor[] monitors = monitorSupplier.get(); @@ -255,11 +261,15 @@ private Point getPointFromPixels(Monitor monitor, int x, int y) { int zoom = getApplicableMonitorZoom(monitor); int mappedX = DPIUtil.scaleDown(x - monitor.clientX, zoom) + monitor.clientX; int mappedY = DPIUtil.scaleDown(y - monitor.clientY, zoom) + monitor.clientY; - return new Point(mappedX, mappedY); + return new MonitorAwarePoint(mappedX, mappedY, monitor); } private int getApplicableMonitorZoom(Monitor monitor) { return DPIUtil.getZoomForAutoscaleProperty(monitor.zoom); } + + + + } \ No newline at end of file diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Shell.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Shell.java index 108e948da44..b82d7a223fe 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Shell.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Shell.java @@ -1595,7 +1595,8 @@ public void setLocation(int x, int y) { public void setBounds(Rectangle rect) { if (rect == null) error (SWT.ERROR_NULL_ARGUMENT); checkWidget (); - Point topLeftInPixels = getDisplay().translateToDisplayCoordinates(new Point(rect.x, rect.y), getZoom()); + Monitor monitor = rect instanceof MonitorAwareRectangle monitorAwareRect ? monitorAwareRect.getMonitor() : null; + Point topLeftInPixels = getDisplay().translateToDisplayCoordinates(new MonitorAwarePoint(rect.x, rect.y, monitor), getZoom()); setBoundsInPixels(topLeftInPixels.x, topLeftInPixels.y, DPIUtil.scaleUp(rect.width, getZoom()), DPIUtil.scaleUp(rect.height, getZoom())); }