From 0e7f799a11eadbeaf072c4639fed6b99470b0423 Mon Sep 17 00:00:00 2001 From: Andreas Koch Date: Tue, 12 Nov 2024 11:12:39 +0100 Subject: [PATCH] [win32] Apply coordinate system change with guards This commit reapplies the essence of the reverted commits from 4f60cb6 and 7a04f7a with proper guards to differentiate between the scenario with rescaling active and inactive. contributes to #62 and #127 --- .../org/eclipse/swt/widgets/Control.java | 17 +- .../org/eclipse/swt/widgets/Display.java | 179 +++++++++++++++++- .../win32/org/eclipse/swt/widgets/Shell.java | 50 +++++ 3 files changed, 234 insertions(+), 12 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java index 10fb35212d4..01ec5ea9f21 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java @@ -3970,6 +3970,11 @@ void subclass () { public Point toControl (int x, int y) { checkWidget (); int zoom = getZoom(); + if (getDisplay().isRescalingAtRuntime()) { + Point displayPointInPixels = getDisplay().translateLocationInPixelsInDisplayCoordinateSystem(x, y); + final Point controlPointInPixels = toControlInPixels(displayPointInPixels.x, displayPointInPixels.y); + return DPIUtil.scaleDown(controlPointInPixels, zoom); + } return DPIUtil.scaleDown(toControlInPixels(DPIUtil.scaleUp(x, zoom), DPIUtil.scaleUp(y, zoom)), zoom); } @@ -4003,9 +4008,7 @@ Point toControlInPixels (int x, int y) { public Point toControl (Point point) { checkWidget (); if (point == null) error (SWT.ERROR_NULL_ARGUMENT); - int zoom = getZoom(); - point = DPIUtil.scaleUp(point, zoom); - return DPIUtil.scaleDown(toControlInPixels(point.x, point.y), zoom); + return toControl(point.x, point.y); } /** @@ -4031,6 +4034,10 @@ public Point toControl (Point point) { public Point toDisplay (int x, int y) { checkWidget (); int zoom = getZoom(); + if (getDisplay().isRescalingAtRuntime()) { + Point displayPointInPixels = toDisplayInPixels(DPIUtil.scaleUp(x, zoom), DPIUtil.scaleUp(y, zoom)); + return getDisplay().translateLocationInPointInDisplayCoordinateSystem(displayPointInPixels.x, displayPointInPixels.y); + } return DPIUtil.scaleDown(toDisplayInPixels(DPIUtil.scaleUp(x, zoom), DPIUtil.scaleUp(y, zoom)), zoom); } @@ -4064,9 +4071,7 @@ Point toDisplayInPixels (int x, int y) { public Point toDisplay (Point point) { checkWidget (); if (point == null) error (SWT.ERROR_NULL_ARGUMENT); - int zoom = getZoom(); - point = DPIUtil.scaleUp(point, zoom); - return DPIUtil.scaleDown(toDisplayInPixels(point.x, point.y), zoom); + return toDisplay(point.x, point.y); } long topHandle () { 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 0c8a71f4d02..2871c11890c 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 @@ -1704,7 +1704,11 @@ public Control getCursorControl () { */ public Point getCursorLocation () { checkDevice (); - return DPIUtil.autoScaleDown(getCursorLocationInPixels()); + Point cursorLocationInPixels = getCursorLocationInPixels(); + if (isRescalingAtRuntime()) { + return translateLocationInPointInDisplayCoordinateSystem(cursorLocationInPixels.x, cursorLocationInPixels.y); + } + return DPIUtil.autoScaleDown(cursorLocationInPixels); } Point getCursorLocationInPixels () { @@ -2183,14 +2187,21 @@ Monitor getMonitor (long hmonitor) { OS.GetMonitorInfo (hmonitor, lpmi); Monitor monitor = new Monitor (); monitor.handle = hmonitor; - Rectangle boundsInPixels = new Rectangle (lpmi.rcMonitor_left, lpmi.rcMonitor_top, lpmi.rcMonitor_right - lpmi.rcMonitor_left,lpmi.rcMonitor_bottom - lpmi.rcMonitor_top); - monitor.setBounds (DPIUtil.autoScaleDown (boundsInPixels)); - Rectangle clientAreaInPixels = new Rectangle (lpmi.rcWork_left, lpmi.rcWork_top, lpmi.rcWork_right - lpmi.rcWork_left, lpmi.rcWork_bottom - lpmi.rcWork_top); - monitor.setClientArea (DPIUtil.autoScaleDown (clientAreaInPixels)); + Rectangle boundsInPixels = new Rectangle(lpmi.rcMonitor_left, lpmi.rcMonitor_top, lpmi.rcMonitor_right - lpmi.rcMonitor_left,lpmi.rcMonitor_bottom - lpmi.rcMonitor_top); + Rectangle clientAreaInPixels = new Rectangle(lpmi.rcWork_left, lpmi.rcWork_top, lpmi.rcWork_right - lpmi.rcWork_left, lpmi.rcWork_bottom - lpmi.rcWork_top); int [] dpiX = new int[1]; int [] dpiY = new int[1]; int result = OS.GetDpiForMonitor (monitor.handle, OS.MDT_EFFECTIVE_DPI, dpiX, dpiY); result = (result == OS.S_OK) ? DPIUtil.mapDPIToZoom (dpiX[0]) : 100; + + if (DPIUtil.isAutoScaleOnRuntimeActive()) { + int autoscaleZoom = DPIUtil.getZoomForAutoscaleProperty(result); + monitor.setBounds(getMonitorBoundsInPointsInDisplayCoordinateSystem(boundsInPixels, autoscaleZoom)); + monitor.setClientArea(getMonitorBoundsInPointsInDisplayCoordinateSystem(clientAreaInPixels, autoscaleZoom)); + } else { + monitor.setBounds(DPIUtil.autoScaleDown(boundsInPixels)); + monitor.setClientArea(DPIUtil.autoScaleDown(clientAreaInPixels)); + } if (result == 0) { System.err.println("***WARNING: GetDpiForMonitor: SWT could not get valid monitor scaling factor."); result = 100; @@ -2203,6 +2214,13 @@ Monitor getMonitor (long hmonitor) { return monitor; } +private Rectangle getMonitorBoundsInPointsInDisplayCoordinateSystem(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. * @@ -2944,6 +2962,9 @@ boolean isValidThread () { public Point map (Control from, Control to, Point point) { checkDevice (); if (point == null) error (SWT.ERROR_NULL_ARGUMENT); + if (isRescalingAtRuntime()) { + return map(from, to, point.x, point.y); + } int zoom = getZoomLevelForMapping(from, to); point = DPIUtil.scaleUp(point, zoom); return DPIUtil.scaleDown(mapInPixels(from, to, point), zoom); @@ -2991,6 +3012,20 @@ Point mapInPixels (Control from, Control to, Point point) { */ public Point map (Control from, Control to, int x, int y) { checkDevice (); + if (isRescalingAtRuntime()) { + Point mappedPointInPoints; + if (from == null) { + Point mappedPointInpixels = mapInPixels(from, to, getPixelsFromPoint(to.getShell().getMonitor(), x, y)); + mappedPointInPoints = DPIUtil.scaleDown(mappedPointInpixels, to.getZoom()); + } else if (to == null) { + Point mappedPointInpixels = mapInPixels(from, to, DPIUtil.scaleUp(new Point(x, y), from.getZoom())); + mappedPointInPoints = getPointFromPixels(from.getShell().getMonitor(), mappedPointInpixels.x, mappedPointInpixels.y); + } else { + Point mappedPointInpixels = mapInPixels(from, to, DPIUtil.scaleUp(new Point(x, y), from.getZoom())); + mappedPointInPoints = DPIUtil.scaleDown(mappedPointInpixels, to.getZoom()); + } + return mappedPointInPoints; + } int zoom = getZoomLevelForMapping(from, to); x = DPIUtil.scaleUp(x, zoom); y = DPIUtil.scaleUp(y, zoom); @@ -3058,6 +3093,9 @@ private int getZoomLevelForMapping(Control from, Control to) { public Rectangle map (Control from, Control to, Rectangle rectangle) { checkDevice (); if (rectangle == null) error (SWT.ERROR_NULL_ARGUMENT); + if (isRescalingAtRuntime()) { + return map(from, to, rectangle.x, rectangle.y, rectangle.width, rectangle.height); + } int zoom = getZoomLevelForMapping(from, to); rectangle = DPIUtil.scaleUp(rectangle, zoom); return DPIUtil.scaleDown(mapInPixels(from, to, rectangle), zoom); @@ -3107,6 +3145,20 @@ Rectangle mapInPixels (Control from, Control to, Rectangle rectangle) { */ public Rectangle map (Control from, Control to, int x, int y, int width, int height) { checkDevice (); + if (isRescalingAtRuntime()) { + Rectangle mappedRectangleInPoints; + if (from == null) { + Rectangle mappedRectangleInPixels = mapInPixels(from, to, translateRectangleInPixelsInDisplayCoordinateSystem(x, y, width, height, to.getShell().getMonitor())); + mappedRectangleInPoints = DPIUtil.scaleDown(mappedRectangleInPixels, to.getZoom()); + } else if (to == null) { + Rectangle mappedRectangleInPixels = mapInPixels(from, to, DPIUtil.scaleUp(new Rectangle(x, y, width, height), from.getZoom())); + mappedRectangleInPoints = translateRectangleInPointsInDisplayCoordinateSystem(mappedRectangleInPixels.x, mappedRectangleInPixels.y, mappedRectangleInPixels.width, mappedRectangleInPixels.height, from.getShell().getMonitor()); + } else { + Rectangle mappedRectangleInPixels = mapInPixels(from, to, DPIUtil.scaleUp(new Rectangle(x, y, width, height), from.getZoom())); + mappedRectangleInPoints = DPIUtil.scaleDown(mappedRectangleInPixels, to.getZoom()); + } + return mappedRectangleInPoints; + } int zoom = getZoomLevelForMapping(from, to); x = DPIUtil.scaleUp(x, zoom); y = DPIUtil.scaleUp(y, zoom); @@ -3130,6 +3182,57 @@ Rectangle mapInPixels (Control from, Control to, int x, int y, int width, int he return new Rectangle (rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); } +Point translateLocationInPixelsInDisplayCoordinateSystem(int x, int y) { + Monitor monitor = getContainingMonitor(x, y); + return getPixelsFromPoint(monitor, x, y); +} + +Point translateLocationInPointInDisplayCoordinateSystem(int x, int y) { + Monitor monitor = getContainingMonitorInPixelsCoordinate(x, y); + return getPointFromPixels(monitor, x, y); +} + +Rectangle translateRectangleInPixelsInDisplayCoordinateSystemByContainment(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); + int widthInPixels = DPIUtil.scaleUp(width, zoom); + int heightInPixels = DPIUtil.scaleUp(height, zoom); + return new Rectangle(topLeft.x, topLeft.y, widthInPixels, heightInPixels); +} + +Rectangle translateRectangleInPointsInDisplayCoordinateSystemByContainment(int x, int y, int widthInPixels, int heightInPixels) { + Monitor monitorByLocation = getContainingMonitor(x, y); + Monitor monitorByContainment = getContainingMonitor(x, y, widthInPixels, heightInPixels); + return translateRectangleInPointsInDisplayCoordinateSystem(x, y, widthInPixels, heightInPixels, monitorByLocation, monitorByContainment); +} + +private Rectangle translateRectangleInPointsInDisplayCoordinateSystem(int x, int y, int widthInPixels, int heightInPixels, Monitor monitor) { + return translateRectangleInPointsInDisplayCoordinateSystem(x, y, widthInPixels, heightInPixels, monitor, monitor); +} + + +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 int getApplicableMonitorZoom(Monitor monitor) { + return DPIUtil.getZoomForAutoscaleProperty(isRescalingAtRuntime() ? monitor.zoom : getDeviceZoom()); +} + long messageProc (long hwnd, long msg, long wParam, long lParam) { switch ((int)msg) { case SWT_RUNASYNC: { @@ -4355,7 +4458,12 @@ public void sendPostExternalEventDispatchEvent () { */ public void setCursorLocation (int x, int y) { checkDevice (); - setCursorLocationInPixels (DPIUtil.autoScaleUp (x), DPIUtil.autoScaleUp (y)); + if (isRescalingAtRuntime()) { + Point cursorLocationInPixels = translateLocationInPixelsInDisplayCoordinateSystem(x, y); + setCursorLocationInPixels (cursorLocationInPixels.x, cursorLocationInPixels.y); + } else { + setCursorLocationInPixels (DPIUtil.autoScaleUp (x), DPIUtil.autoScaleUp (y)); + } } void setCursorLocationInPixels (int x, int y) { @@ -5390,4 +5498,63 @@ private boolean setDPIAwareness(int desiredDpiAwareness) { return true; } +private Monitor getContainingMonitor(int x, int y) { + Monitor[] monitors = getMonitors(); + for (Monitor currentMonitor : monitors) { + Rectangle clientArea = currentMonitor.getClientArea(); + if (clientArea.contains(x, y)) { + return currentMonitor; + } + } + return getPrimaryMonitor(); +} + +private Monitor getContainingMonitor(int x, int y, int width, int height) { + Rectangle rectangle = new Rectangle(x, y, width, height); + Monitor[] monitors = getMonitors(); + Monitor selectedMonitor = getPrimaryMonitor(); + int highestArea = 0; + for (Monitor currentMonitor : monitors) { + Rectangle clientArea = currentMonitor.getClientArea(); + Rectangle intersection = clientArea.intersection(rectangle); + int area = intersection.width * intersection.height; + if (area > highestArea) { + selectedMonitor = currentMonitor; + highestArea = area; + } + } + return selectedMonitor; +} + +private Monitor getContainingMonitorInPixelsCoordinate(int xInPixels, int yInPixels) { + Monitor[] monitors = getMonitors(); + for (Monitor current : monitors) { + Rectangle clientArea = getMonitorClientAreaInPixels(current); + if (clientArea.contains(xInPixels, yInPixels)) { + return current; + } + } + return getPrimaryMonitor(); +} + +private Rectangle getMonitorClientAreaInPixels(Monitor monitor) { + int zoom = getApplicableMonitorZoom(monitor); + int widthInPixels = DPIUtil.scaleUp(monitor.clientWidth, zoom); + int heightInPixels = DPIUtil.scaleUp(monitor.clientHeight, zoom); + return new Rectangle(monitor.clientX, monitor.clientY, widthInPixels, heightInPixels); +} + +private Point getPixelsFromPoint(Monitor monitor, int x, int y) { + int zoom = getApplicableMonitorZoom(monitor); + int mappedX = DPIUtil.scaleUp(x - monitor.clientX, zoom) + monitor.clientX; + int mappedY = DPIUtil.scaleUp(y - monitor.clientY, zoom) + monitor.clientY; + return new Point(mappedX, mappedY); +} + +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); +} } 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 f7a75caf757..f30872a8c3a 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 @@ -1566,6 +1566,56 @@ public void setAlpha (int alpha) { } } +@Override +public Rectangle getBounds() { + if (getDisplay().isRescalingAtRuntime()) { + Rectangle boundsInPixels = getBoundsInPixels(); + return display.translateRectangleInPointsInDisplayCoordinateSystemByContainment(boundsInPixels.x, boundsInPixels.y, boundsInPixels.width, boundsInPixels.height); + } + return super.getBounds(); +} + +@Override +public Point getLocation() { + if (getDisplay().isRescalingAtRuntime()) { + Point locationInPixels = getLocationInPixels(); + return display.translateLocationInPointInDisplayCoordinateSystem(locationInPixels.x, locationInPixels.y); + } + return super.getLocation(); +} + +@Override +public void setLocation(Point location) { + if (location == null) error (SWT.ERROR_NULL_ARGUMENT); + setLocation(location.x, location.y); +} + +@Override +public void setLocation(int x, int y) { + if (getDisplay().isRescalingAtRuntime()) { + Point location = display.translateLocationInPixelsInDisplayCoordinateSystem(x, y); + setLocationInPixels(location.x, location.y); + } else { + super.setLocation(x, y); + } +} + +@Override +public void setBounds(Rectangle rect) { + if (rect == null) error (SWT.ERROR_NULL_ARGUMENT); + setBounds(rect.x, rect.y, rect.width, rect.height); +} + +@Override +public void setBounds(int x, int y, int width, int height) { + if (getDisplay().isRescalingAtRuntime()) { + Rectangle boundsInPixels = display.translateRectangleInPixelsInDisplayCoordinateSystemByContainment(x, y, width, height); + setBoundsInPixels(boundsInPixels.x, boundsInPixels.y, boundsInPixels.width, boundsInPixels.height); + } else { + super.setBounds(x, y, width, height); + } +} + @Override void setBoundsInPixels (int x, int y, int width, int height, int flags, boolean defer) { if (fullScreen) setFullScreen (false);