From cd65f15a67e626a11bf85d44e049f3a6722101d5 Mon Sep 17 00:00:00 2001 From: Andreas Koch Date: Wed, 26 Jun 2024 14:25:21 +0200 Subject: [PATCH] Redesigned the Display coordinate system for win32 This commit enforces displays to store x,y coordinates in point as the absolute pixels in the display coordinate system. while scaling the width and height to the points, following this the map methods are reimplemented to do the right conversion between the new display coordinate system and the coordinates within a control. contributes to #62 and #127 --- .../org/eclipse/swt/widgets/Control.java | 16 +- .../org/eclipse/swt/widgets/Display.java | 157 ++++++++++++++---- .../win32/org/eclipse/swt/widgets/Shell.java | 43 +++++ 3 files changed, 176 insertions(+), 40 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 9c1f6c9e5c1..454506f65c2 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 @@ -3969,8 +3969,9 @@ void subclass () { */ public Point toControl (int x, int y) { checkWidget (); - int zoom = getZoom(); - return DPIUtil.scaleDown(toControlInPixels(DPIUtil.scaleUp(x, zoom), DPIUtil.scaleUp(y, zoom)), zoom); + Point displayPointInPixels = getDisplay().translateLocationInPixelsInDisplayCoordinateSystem(x, y); + final Point controlPointInPixels = toControlInPixels(displayPointInPixels.x, displayPointInPixels.y); + return DPIUtil.scaleDown(controlPointInPixels, getZoom()); } Point toControlInPixels (int x, int y) { @@ -4003,9 +4004,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,7 +4030,8 @@ public Point toControl (Point point) { public Point toDisplay (int x, int y) { checkWidget (); int zoom = getZoom(); - return DPIUtil.scaleDown(toDisplayInPixels(DPIUtil.scaleUp(x, zoom), DPIUtil.scaleUp(y, zoom)), zoom); + Point displayPointInPixels = toDisplayInPixels(DPIUtil.scaleUp(x, zoom), DPIUtil.scaleUp(y, zoom)); + return getDisplay().translateLocationInPointInDisplayCoordinateSystem(displayPointInPixels); } Point toDisplayInPixels (int x, int y) { @@ -4064,9 +4064,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 13c0e43ffae..f2116387d3f 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 @@ -1691,7 +1691,8 @@ public Control getCursorControl () { */ public Point getCursorLocation () { checkDevice (); - return DPIUtil.autoScaleDown(getCursorLocationInPixels()); + Point cursorLocationInPixels = getCursorLocationInPixels(); + return translateLocationInPointInDisplayCoordinateSystem(cursorLocationInPixels.x, cursorLocationInPixels.y); } Point getCursorLocationInPixels () { @@ -2170,18 +2171,25 @@ 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; + + int autoscaleZoom; + if (DPIUtil.isAutoScaleOnRuntimeActive()) { + autoscaleZoom = DPIUtil.getZoomForAutoscaleProperty(result); + } else { + autoscaleZoom = DPIUtil.getDeviceZoom(); + } if (result == 0) { System.err.println("***WARNING: GetDpiForMonitor: SWT could not get valid monitor scaling factor."); result = 100; } + monitor.setBounds(getMonitorBoundsInPointsInDisplayCoordinateSystem(boundsInPixels, autoscaleZoom)); + monitor.setClientArea(getMonitorBoundsInPointsInDisplayCoordinateSystem(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. @@ -2190,6 +2198,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. * @@ -2969,9 +2984,7 @@ boolean isValidThread () { public Point map (Control from, Control to, Point point) { checkDevice (); if (point == null) error (SWT.ERROR_NULL_ARGUMENT); - int zoom = getZoomLevelForMapping(from, to); - point = DPIUtil.scaleUp(point, zoom); - return DPIUtil.scaleDown(mapInPixels(from, to, point), zoom); + return map(from, to, point.x, point.y); } Point mapInPixels (Control from, Control to, Point point) { @@ -3016,10 +3029,18 @@ Point mapInPixels (Control from, Control to, Point point) { */ public Point map (Control from, Control to, int x, int y) { checkDevice (); - int zoom = getZoomLevelForMapping(from, to); - x = DPIUtil.scaleUp(x, zoom); - y = DPIUtil.scaleUp(y, zoom); - return DPIUtil.scaleDown(mapInPixels(from, to, x, y), zoom); + Point mappedPointInPoints; + if (from == null) { + Point mappedPointInpixels = mapInPixels(from, to, translateLocationInPixelsInDisplayCoordinateSystem(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 = translateLocationInPointInDisplayCoordinateSystem(mappedPointInpixels); + } else { + Point mappedPointInpixels = mapInPixels(from, to, DPIUtil.scaleUp(new Point(x, y), from.getZoom())); + mappedPointInPoints = DPIUtil.scaleDown(mappedPointInpixels, to.getZoom()); + } + return mappedPointInPoints; } Point mapInPixels (Control from, Control to, int x, int y) { @@ -3035,15 +3056,6 @@ Point mapInPixels (Control from, Control to, int x, int y) { return new Point (point.x, point.y); } -private int getZoomLevelForMapping(Control from, Control to) { - if (from != null && from.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT); - if (to != null && to.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT); - if (to != null) { - return to.getZoom(); - } - return from.getZoom(); -} - /** * Maps a point from one coordinate system to another. * When the control is null, coordinates are mapped to @@ -3083,9 +3095,7 @@ 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); - int zoom = getZoomLevelForMapping(from, to); - rectangle = DPIUtil.scaleUp(rectangle, zoom); - return DPIUtil.scaleDown(mapInPixels(from, to, rectangle), zoom); + return map(from, to, rectangle.x, rectangle.y, rectangle.width, rectangle.height); } Rectangle mapInPixels (Control from, Control to, Rectangle rectangle) { @@ -3132,12 +3142,18 @@ Rectangle mapInPixels (Control from, Control to, Rectangle rectangle) { */ public Rectangle map (Control from, Control to, int x, int y, int width, int height) { checkDevice (); - int zoom = getZoomLevelForMapping(from, to); - x = DPIUtil.scaleUp(x, zoom); - y = DPIUtil.scaleUp(y, zoom); - width = DPIUtil.scaleUp(width, zoom); - height = DPIUtil.scaleUp(height, zoom); - return DPIUtil.scaleDown(mapInPixels(from, to, x, y, width, height), zoom); + Rectangle mappedRectangleInPoints; + if (from == null) { + Rectangle mappedRectangleInPixels = mapInPixels(from, to, translateRectangleInPixelsInDisplayCoordinateSystem(x, y, width, height)); + 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); + } else { + Rectangle mappedRectangleInPixels = mapInPixels(from, to, DPIUtil.scaleUp(new Rectangle(x, y, width, height), from.getZoom())); + mappedRectangleInPoints = DPIUtil.scaleDown(mappedRectangleInPixels, to.getZoom()); + } + return mappedRectangleInPoints; } Rectangle mapInPixels (Control from, Control to, int x, int y, int width, int height) { @@ -3155,6 +3171,42 @@ 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(Point point) { + return translateLocationInPixelsInDisplayCoordinateSystem(point.x, point.y); +} + +Point translateLocationInPixelsInDisplayCoordinateSystem(int x, int y) { + Monitor monitor = getContainingMonitor(x, y); + return getPixelsFromPoint(monitor, x, y); +} + +Point translateLocationInPointInDisplayCoordinateSystem(Point point) { + return translateLocationInPointInDisplayCoordinateSystem(point.x, point.y); +} + +Point translateLocationInPointInDisplayCoordinateSystem(int x, int y) { + Monitor monitor = getContainingMonitorInPixelsCoordiate(x, y); + return getPointFromPixels(monitor, x, y); +} + +private Rectangle translateRectangleInPixelsInDisplayCoordinateSystem(int x, int y, int width, int height) { + Monitor monitor = getContainingMonitor(x, y); + Point topLeft = getPixelsFromPoint(monitor, x, y); + int zoom = DPIUtil.getZoomForAutoscaleProperty(monitor.zoom); + int widthInPixels = DPIUtil.scaleUp(width, zoom); + int heightInPixels = DPIUtil.scaleUp(height, zoom); + return new Rectangle(topLeft.x, topLeft.y, widthInPixels, heightInPixels); +} + +private Rectangle translateRectangleInPointsInDisplayCoordinateSystem(int x, int y, int widthInPixels, int heightInPixels) { + Monitor monitor = getContainingMonitor(x, y); + Point topLeft = getPointFromPixels(monitor, x, y); + int zoom = DPIUtil.getZoomForAutoscaleProperty(monitor.zoom); + int width = DPIUtil.scaleDown(widthInPixels, zoom); + int height = DPIUtil.scaleDown(heightInPixels, zoom); + return new Rectangle(topLeft.x, topLeft.y, width, height); +} + long messageProc (long hwnd, long msg, long wParam, long lParam) { switch ((int)msg) { case SWT_RUNASYNC: { @@ -4380,7 +4432,8 @@ public void sendPostExternalEventDispatchEvent () { */ public void setCursorLocation (int x, int y) { checkDevice (); - setCursorLocationInPixels (DPIUtil.autoScaleUp (x), DPIUtil.autoScaleUp (y)); + Point cursorLocationInPixels = translateLocationInPixelsInDisplayCoordinateSystem(x, y); + setCursorLocationInPixels (cursorLocationInPixels.x, cursorLocationInPixels.y); } void setCursorLocationInPixels (int x, int y) { @@ -5306,4 +5359,46 @@ private void setProperDPIAwareness() { } } +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(); +} + +Monitor getContainingMonitorInPixelsCoordiate(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 = DPIUtil.getZoomForAutoscaleProperty(monitor.zoom); + 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 = 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); +} + +private Point getPointFromPixels(Monitor monitor, int x, int 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); +} } 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 64bd00650d0..dcd2fcba76f 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 @@ -1571,6 +1571,49 @@ public void setAlpha (int alpha) { } } +@Override +public Rectangle getBounds() { + Rectangle boundsInPixels = getBoundsInPixels(); + Rectangle bounds = DPIUtil.scaleDown(boundsInPixels, getZoom()); + Point pointWithMonitorOffset = display.translateLocationInPointInDisplayCoordinateSystem(boundsInPixels.x, boundsInPixels.y); + bounds.x = pointWithMonitorOffset.x; + bounds.y = pointWithMonitorOffset.y; + return bounds; +} + +@Override +public Point getLocation() { + Point locationInPixels = getLocationInPixels(); + return display.translateLocationInPointInDisplayCoordinateSystem(locationInPixels.x, locationInPixels.y); +} + +@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) { + Point location = display.translateLocationInPixelsInDisplayCoordinateSystem(x, y); + setLocationInPixels(location.x, location.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) { + Point topLeft = display.translateLocationInPixelsInDisplayCoordinateSystem(x, y); + final int zoom = getZoom(); + int widthInPixels = DPIUtil.scaleUp(width, zoom); + int heightInPixels = DPIUtil.scaleUp(height, zoom); + setBoundsInPixels(topLeft.x, topLeft.y, widthInPixels, heightInPixels); +} + @Override void setBoundsInPixels (int x, int y, int width, int height, int flags, boolean defer) { if (fullScreen) setFullScreen (false);