From 669160fb3ce2b3ab2c43853f3653c6c3e01a3941 Mon Sep 17 00:00:00 2001 From: Amartya Parijat Date: Wed, 17 Jul 2024 15:20:52 +0200 Subject: [PATCH] Monitor Position Offset for multi zoom level This commit introduces the offsetting of the monitor position to obtain the absolute and scaled down bounds of the monitor for seamlessly translating the positioning of the shell at any zoom levels. With this, we fix several behaviour in multi zoom - multi monitor set up for win32, such as, proper positioning of the shell and the overlay on dragging, opening of a new window in the right monitor,etc. contributes to #62 and #127 --- .../org/eclipse/swt/widgets/Display.java | 44 +++++++++++++++++-- .../win32/org/eclipse/swt/widgets/Shell.java | 39 ++++++++++++++-- 2 files changed, 76 insertions(+), 7 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java index 54e1b6c9d7..b4fb5423aa 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java @@ -1687,7 +1687,8 @@ public Control getCursorControl () { */ public Point getCursorLocation () { checkDevice (); - return DPIUtil.autoScaleDown(getCursorLocationInPixels()); + Point pt = getCursorLocationInPixels(); + return getLocationInPointWithMonitorOffset(pt.x, pt.y); } Point getCursorLocationInPixels () { @@ -1696,6 +1697,22 @@ Point getCursorLocationInPixels () { return new Point (pt.x, pt.y); } +Point getLocationInPixelsWithMonitorOffset(int x, int y) { + Monitor monitor = getContainingMonitor(x, y); + int zoom = DPIUtil.getZoomForAutoscaleProperty(monitor.zoom); + x = DPIUtil.scaleUp(x - monitor.clientX, zoom) + monitor.clientX; + y = DPIUtil.scaleUp(y - monitor.clientY, zoom) + monitor.clientY; + return new Point(x, y); +} + +Point getLocationInPointWithMonitorOffset(int x, int y) { + Monitor monitor = getContainingMonitorInPixelsCoordiate(x, y); + int zoom = DPIUtil.getZoomForAutoscaleProperty(monitor.zoom); + x = DPIUtil.scaleDown(x - monitor.clientX, zoom) + monitor.clientX; + y = DPIUtil.scaleDown(y - monitor.clientY, zoom) + monitor.clientY; + return new Point(x, y); +} + /** * Returns an array containing the recommended cursor sizes. * @@ -2183,8 +2200,8 @@ Monitor getMonitor (long hmonitor) { System.err.println("***WARNING: GetDpiForMonitor: SWT could not get valid monitor scaling factor."); result = 100; } - monitor.setBounds(DPIUtil.scaleDown(boundsInPixels, autoscaleZoom)); - monitor.setClientArea(DPIUtil.scaleDown(clientAreaInPixels, autoscaleZoom)); + monitor.setBounds(getBoundsInPointsWithMonitorOffset(boundsInPixels, autoscaleZoom)); + monitor.setClientArea(getBoundsInPointsWithMonitorOffset(clientAreaInPixels, autoscaleZoom)); /* * Always return true monitor zoom value as fetched from native, else will lead * to scaling issue on OS Win8.1 and above, for more details refer bug 537614. @@ -2193,6 +2210,13 @@ Monitor getMonitor (long hmonitor) { return monitor; } +private Rectangle getBoundsInPointsWithMonitorOffset(Rectangle boundsInPixels, int zoom) { + Rectangle bounds = DPIUtil.scaleDown(boundsInPixels, zoom); + bounds.x = boundsInPixels.x; + bounds.y = boundsInPixels.y; + return bounds; +} + /** * Returns an array of monitors attached to the device. * @@ -5262,4 +5286,18 @@ Monitor getContainingMonitor(int x, int y) { } return getPrimaryMonitor(); } + +Monitor getContainingMonitorInPixelsCoordiate(int xInPixels, int yInPixels) { + Monitor[] monitors = getMonitors(); + for (Monitor current : monitors) { + Rectangle clientArea = DPIUtil.scaleUp(current.getClientArea(), DPIUtil.getZoomForAutoscaleProperty(current.zoom)); + clientArea.x = current.clientX; + clientArea.y = current.clientY; + if (clientArea.contains(xInPixels, yInPixels)) { + return current; + } + } + return getPrimaryMonitor(); +} + } 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 a9ab293f7c..ef7137fdcf 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 @@ -1579,30 +1579,61 @@ private void updateNativeZoomBeforePositionChange(int x, int y) { } } +@Override +public Rectangle getBounds() { + Rectangle boundsInPixels = getBoundsInPixels (); + Rectangle bounds = DPIUtil.scaleDown(boundsInPixels, getZoom()); + Point pointWithMonitorOffset = display.getLocationInPointWithMonitorOffset(boundsInPixels.x, boundsInPixels.y); + bounds.x = pointWithMonitorOffset.x; + bounds.y = pointWithMonitorOffset.y; + return bounds; +} + +@Override +public Point getLocation() { + Point locationInPixels = getLocationInPixels(); + Point location = display.getLocationInPointWithMonitorOffset(locationInPixels.x, locationInPixels.y); + return location; +} + @Override public void setLocation(Point location) { if (location == null) error (SWT.ERROR_NULL_ARGUMENT); updateNativeZoomBeforePositionChange(location.x, location.y); - super.setLocation(location); + location = display.getLocationInPixelsWithMonitorOffset(location.x, location.y); + setLocationInPixels(location.x, location.y); } @Override public void setLocation(int x, int y) { updateNativeZoomBeforePositionChange(x, y); - super.setLocation(x, y); + Point location = display.getLocationInPixelsWithMonitorOffset(x, y); + x = location.x; + y = location.y; + setLocationInPixels(x, y); } @Override public void setBounds(Rectangle rect) { if (rect == null) error (SWT.ERROR_NULL_ARGUMENT); updateNativeZoomBeforePositionChange(rect.x, rect.y); - super.setBounds(rect); + Rectangle scaledBounds = DPIUtil.scaleUp(rect, getZoom()); + Point topLeft = display.getLocationInPixelsWithMonitorOffset(rect.x, rect.y); + scaledBounds.x = topLeft.x; + scaledBounds.y = topLeft.y; + setBoundsInPixels(scaledBounds); } @Override public void setBounds(int x, int y, int width, int height) { updateNativeZoomBeforePositionChange(x, y); - super.setBounds(x, y, width, height); + int zoom = getZoom(); + Point topLeft = display.getLocationInPixelsWithMonitorOffset(x, y); + x = topLeft.x; + y = topLeft.y; + width = DPIUtil.scaleUp(width, zoom); + height = DPIUtil.scaleUp(height, zoom); + setBoundsInPixels(x, y, width, height); } @Override