From a4a2c67f50b81003507a773751ce3fa28a886e14 Mon Sep 17 00:00:00 2001 From: Amartya Parijat Date: Fri, 12 Apr 2024 16:30:03 +0200 Subject: [PATCH] Multi zoom level support of GC for win32 This commit contributes to multi zoom level support of GC which can be extended by other resources and widgets. Contributes to https://github.com/eclipse-platform/eclipse.platform.swt/issues/62 and https://github.com/eclipse-platform/eclipse.platform.swt/issues/131 --- .../Eclipse SWT PI/win32/library/os.c | 14 +- .../Eclipse SWT PI/win32/library/os_stats.h | 3 +- .../org/eclipse/swt/internal/win32/OS.java | 3 + .../org/eclipse/swt/internal/DPIUtil.java | 4 + .../win32/org/eclipse/swt/graphics/GC.java | 238 +++++++++++------- .../org/eclipse/swt/graphics/GCData.java | 1 + .../win32/org/eclipse/swt/graphics/Image.java | 1 + .../win32/org/eclipse/swt/widgets/Button.java | 2 +- .../org/eclipse/swt/widgets/Composite.java | 4 +- .../org/eclipse/swt/widgets/Control.java | 1 + .../org/eclipse/swt/widgets/Display.java | 1 + .../org/eclipse/swt/widgets/ExpandBar.java | 2 +- .../win32/org/eclipse/swt/widgets/Label.java | 2 +- .../org/eclipse/swt/widgets/MenuItem.java | 2 +- .../win32/org/eclipse/swt/widgets/Table.java | 14 +- .../win32/org/eclipse/swt/widgets/Tree.java | 20 +- .../win32/org/eclipse/swt/widgets/Widget.java | 5 + .../eclipse/swt/graphics/GCWin32Tests.java | 88 +++++++ .../org/eclipse/swt/internal/DPITestUtil.java | 9 + 19 files changed, 293 insertions(+), 121 deletions(-) create mode 100644 tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/graphics/GCWin32Tests.java create mode 100644 tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/internal/DPITestUtil.java diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os.c b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os.c index f6c8dbdce79..8e864c9a713 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os.c +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2023 IBM Corporation and others. + * Copyright (c) 2000, 2024 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -2022,6 +2022,18 @@ JNIEXPORT jlong JNICALL OS_NATIVE(GetActiveWindow) } #endif +#ifndef NO_GetAncestor +JNIEXPORT jlong JNICALL OS_NATIVE(GetAncestor) + (JNIEnv *env, jclass that, jlong arg0, jint arg1) +{ + jlong rc = 0; + OS_NATIVE_ENTER(env, that, GetAncestor_FUNC); + rc = (jlong)GetAncestor((HWND)arg0, arg1); + OS_NATIVE_EXIT(env, that, GetAncestor_FUNC); + return rc; +} +#endif + #ifndef NO_GetBkColor JNIEXPORT jint JNICALL OS_NATIVE(GetBkColor) (JNIEnv *env, jclass that, jlong arg0) diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.h b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.h index 6fbcd0fc91e..7bbf84350a6 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.h +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/library/os_stats.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2023 IBM Corporation and others. + * Copyright (c) 2000, 2024 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -170,6 +170,7 @@ typedef enum { GdiSetBatchLimit_FUNC, GetACP_FUNC, GetActiveWindow_FUNC, + GetAncestor_FUNC, GetBkColor_FUNC, GetCapture_FUNC, GetCaretPos_FUNC, diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java index f32d0ea3a8e..2c57c38fc85 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/win32/org/eclipse/swt/internal/win32/OS.java @@ -497,6 +497,7 @@ public class OS extends C { public static final int FR_PRIVATE = 0x10; public static final int FSHIFT = 0x4; public static final int FVIRTKEY = 0x1; + public static final int GA_ROOT = 0x2; public static final int GCP_REORDER = 0x0002; public static final int GCP_GLYPHSHAPE = 0x0010; public static final int GCP_CLASSIN = 0x00080000; @@ -2709,6 +2710,8 @@ public static int HRESULT_FROM_WIN32(int x) { public static final native int GdiSetBatchLimit (int dwLimit); public static final native int GetACP (); public static final native long GetActiveWindow (); +/** @param hWnd cast=(HWND) */ +public static final native long GetAncestor (long hWnd, int gaFlags); /** @param hDC cast=(HDC) */ public static final native int GetBkColor (long hDC); public static final native long GetCapture (); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java index 56ad6bc0a2a..01a8ff29024 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java @@ -665,6 +665,10 @@ public static boolean isAutoScaleOnRuntimeActive() { return autoScaleOnRuntime; } +static boolean setAutoScaleOnRuntimeActive(boolean value) { + return autoScaleOnRuntime = value; +} + /** * AutoScale ImageDataProvider. */ diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java index 8d779a891de..0363fc131ef 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GC.java @@ -455,8 +455,9 @@ void checkGC(int mask) { * */ public void copyArea (Image image, int x, int y) { - x = DPIUtil.autoScaleUp(drawable, x); - y = DPIUtil.autoScaleUp(drawable, y); + int deviceZoom = getDeviceZoom(); + x = DPIUtil.autoScaleUp(drawable, x, deviceZoom); + y = DPIUtil.autoScaleUp(drawable, y, deviceZoom); copyAreaInPixels(image, x, y); } @@ -511,12 +512,13 @@ public void copyArea (int srcX, int srcY, int width, int height, int destX, int * @since 3.1 */ public void copyArea (int srcX, int srcY, int width, int height, int destX, int destY, boolean paint) { - srcX = DPIUtil.autoScaleUp(drawable, srcX); - srcY = DPIUtil.autoScaleUp(drawable, srcY); - width = DPIUtil.autoScaleUp(drawable, width); - height = DPIUtil.autoScaleUp(drawable, height); - destX = DPIUtil.autoScaleUp(drawable, destX); - destY = DPIUtil.autoScaleUp(drawable, destY); + int deviceZoom = getDeviceZoom(); + srcX = DPIUtil.autoScaleUp(drawable, srcX, deviceZoom); + srcY = DPIUtil.autoScaleUp(drawable, srcY, deviceZoom); + width = DPIUtil.autoScaleUp(drawable, width, deviceZoom); + height = DPIUtil.autoScaleUp(drawable, height, deviceZoom); + destX = DPIUtil.autoScaleUp(drawable, destX, deviceZoom); + destY = DPIUtil.autoScaleUp(drawable, destY, deviceZoom); copyAreaInPixels(srcX, srcY, width, height, destX, destY, paint); } @@ -757,10 +759,11 @@ void disposeGdip() { * */ public void drawArc (int x, int y, int width, int height, int startAngle, int arcAngle) { - x = DPIUtil.autoScaleUp(drawable, x); - y = DPIUtil.autoScaleUp(drawable, y); - width = DPIUtil.autoScaleUp(drawable, width); - height = DPIUtil.autoScaleUp(drawable, height); + int deviceZoom = getDeviceZoom(); + x = DPIUtil.autoScaleUp(drawable, x, deviceZoom); + y = DPIUtil.autoScaleUp(drawable, y, deviceZoom); + width = DPIUtil.autoScaleUp(drawable, width, deviceZoom); + height = DPIUtil.autoScaleUp(drawable, height, deviceZoom); drawArcInPixels(x, y, width, height, startAngle, arcAngle); } @@ -840,10 +843,11 @@ void drawArcInPixels (int x, int y, int width, int height, int startAngle, int a * @see #drawRectangle(int, int, int, int) */ public void drawFocus (int x, int y, int width, int height) { - x = DPIUtil.autoScaleUp (drawable, x); - y = DPIUtil.autoScaleUp (drawable, y); - width = DPIUtil.autoScaleUp (drawable, width); - height = DPIUtil.autoScaleUp (drawable, height); + int deviceZoom = getDeviceZoom(); + x = DPIUtil.autoScaleUp (drawable, x, deviceZoom); + y = DPIUtil.autoScaleUp (drawable, y, deviceZoom); + width = DPIUtil.autoScaleUp (drawable, width, deviceZoom); + height = DPIUtil.autoScaleUp (drawable, height, deviceZoom); drawFocusInPixels(x, y, width, height); } @@ -918,8 +922,9 @@ void drawFocusInPixels (int x, int y, int width, int height) { * */ public void drawImage (Image image, int x, int y) { - x = DPIUtil.autoScaleUp(drawable, x); - y = DPIUtil.autoScaleUp(drawable, y); + int deviceZoom = getDeviceZoom(); + x = DPIUtil.autoScaleUp(drawable, x, deviceZoom); + y = DPIUtil.autoScaleUp(drawable, y, deviceZoom); drawImageInPixels(image, x, y); } @@ -971,9 +976,9 @@ public void drawImage (Image image, int srcX, int srcY, int srcWidth, int srcHei if (image == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); - Rectangle src = DPIUtil.autoScaleUp(drawable, new Rectangle(srcX, srcY, srcWidth, srcHeight)); - Rectangle dest = DPIUtil.autoScaleUp(drawable, new Rectangle(destX, destY, destWidth, destHeight)); - int deviceZoom = DPIUtil.getDeviceZoom(); + int deviceZoom = getDeviceZoom(); + Rectangle src = DPIUtil.autoScaleUp(drawable, new Rectangle(srcX, srcY, srcWidth, srcHeight), deviceZoom); + Rectangle dest = DPIUtil.autoScaleUp(drawable, new Rectangle(destX, destY, destWidth, destHeight), deviceZoom); if (deviceZoom != 100) { /* * This is a HACK! Due to rounding errors at fractional scale factors, @@ -1640,10 +1645,11 @@ void drawBitmapColor(Image srcImage, int srcX, int srcY, int srcWidth, int srcHe * */ public void drawLine (int x1, int y1, int x2, int y2) { - x1 = DPIUtil.autoScaleUp (drawable, x1); - x2 = DPIUtil.autoScaleUp (drawable, x2); - y1 = DPIUtil.autoScaleUp (drawable, y1); - y2 = DPIUtil.autoScaleUp (drawable, y2); + int deviceZoom = getDeviceZoom(); + x1 = DPIUtil.autoScaleUp (drawable, x1, deviceZoom); + x2 = DPIUtil.autoScaleUp (drawable, x2, deviceZoom); + y1 = DPIUtil.autoScaleUp (drawable, y1, deviceZoom); + y2 = DPIUtil.autoScaleUp (drawable, y2, deviceZoom); drawLineInPixels(x1, y1, x2, y2); } @@ -1692,10 +1698,11 @@ void drawLineInPixels (int x1, int y1, int x2, int y2) { * */ public void drawOval (int x, int y, int width, int height) { - x = DPIUtil.autoScaleUp (drawable, x); - y = DPIUtil.autoScaleUp (drawable, y); - width = DPIUtil.autoScaleUp (drawable, width); - height = DPIUtil.autoScaleUp (drawable, height); + int deviceZoom = getDeviceZoom(); + x = DPIUtil.autoScaleUp (drawable, x, deviceZoom); + y = DPIUtil.autoScaleUp (drawable, y, deviceZoom); + width = DPIUtil.autoScaleUp (drawable, width, deviceZoom); + height = DPIUtil.autoScaleUp (drawable, height, deviceZoom); drawOvalInPixels(x, y, width, height); } @@ -1768,8 +1775,9 @@ public void drawPath (Path path) { * @since 3.0 */ public void drawPoint (int x, int y) { - x = DPIUtil.autoScaleUp (drawable, x); - y = DPIUtil.autoScaleUp (drawable, y); + int deviceZoom = getDeviceZoom(); + x = DPIUtil.autoScaleUp (drawable, x, deviceZoom); + y = DPIUtil.autoScaleUp (drawable, y, deviceZoom); drawPointInPixels(x, y); } @@ -1802,7 +1810,7 @@ void drawPointInPixels (int x, int y) { */ public void drawPolygon (int[] pointArray) { if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - drawPolygonInPixels(DPIUtil.autoScaleUp(drawable, pointArray)); + drawPolygonInPixels(DPIUtil.autoScaleUp(drawable, pointArray, getDeviceZoom())); } void drawPolygonInPixels(int[] pointArray) { @@ -1850,7 +1858,7 @@ void drawPolygonInPixels(int[] pointArray) { * */ public void drawPolyline (int[] pointArray) { - drawPolylineInPixels(DPIUtil.autoScaleUp(drawable, pointArray)); + drawPolylineInPixels(DPIUtil.autoScaleUp(drawable, pointArray, getDeviceZoom())); } void drawPolylineInPixels(int[] pointArray) { @@ -1903,10 +1911,11 @@ void drawPolylineInPixels(int[] pointArray) { * */ public void drawRectangle (int x, int y, int width, int height) { - x = DPIUtil.autoScaleUp (drawable, x); - y = DPIUtil.autoScaleUp (drawable, y); - width = DPIUtil.autoScaleUp (drawable, width); - height = DPIUtil.autoScaleUp (drawable, height); + int deviceZoom = getDeviceZoom(); + x = DPIUtil.autoScaleUp (drawable, x, deviceZoom); + y = DPIUtil.autoScaleUp (drawable, y, deviceZoom); + width = DPIUtil.autoScaleUp (drawable, width, deviceZoom); + height = DPIUtil.autoScaleUp (drawable, height, deviceZoom); drawRectangleInPixels(x, y, width, height); } @@ -1962,7 +1971,7 @@ void drawRectangleInPixels (int x, int y, int width, int height) { */ public void drawRectangle (Rectangle rect) { if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - rect = DPIUtil.autoScaleUp(drawable, rect); + rect = DPIUtil.autoScaleUp(drawable, rect, getDeviceZoom()); drawRectangleInPixels(rect.x, rect.y, rect.width, rect.height); } @@ -1988,12 +1997,13 @@ public void drawRectangle (Rectangle rect) { * */ public void drawRoundRectangle (int x, int y, int width, int height, int arcWidth, int arcHeight) { - x = DPIUtil.autoScaleUp (drawable, x); - y = DPIUtil.autoScaleUp (drawable, y); - width = DPIUtil.autoScaleUp (drawable, width); - height = DPIUtil.autoScaleUp (drawable, height); - arcWidth = DPIUtil.autoScaleUp (drawable, arcWidth); - arcHeight = DPIUtil.autoScaleUp (drawable, arcHeight); + int deviceZoom = getDeviceZoom(); + x = DPIUtil.autoScaleUp (drawable, x, deviceZoom); + y = DPIUtil.autoScaleUp (drawable, y, deviceZoom); + width = DPIUtil.autoScaleUp (drawable, width, deviceZoom); + height = DPIUtil.autoScaleUp (drawable, height, deviceZoom); + arcWidth = DPIUtil.autoScaleUp (drawable, arcWidth, deviceZoom); + arcHeight = DPIUtil.autoScaleUp (drawable, arcHeight, deviceZoom); drawRoundRectangleInPixels(x, y, width, height, arcWidth, arcHeight); } @@ -2085,8 +2095,9 @@ void drawRoundRectangleGdip (long gdipGraphics, long pen, int x, int y, int widt * */ public void drawString (String string, int x, int y) { - x = DPIUtil.autoScaleUp(drawable, x); - y = DPIUtil.autoScaleUp(drawable, y); + int deviceZoom = getDeviceZoom(); + x = DPIUtil.autoScaleUp(drawable, x, deviceZoom); + y = DPIUtil.autoScaleUp(drawable, y, deviceZoom); drawStringInPixels(string, x, y, false); } @@ -2118,8 +2129,9 @@ public void drawString (String string, int x, int y) { * */ public void drawString (String string, int x, int y, boolean isTransparent) { - x = DPIUtil.autoScaleUp(drawable, x); - y = DPIUtil.autoScaleUp(drawable, y); + int deviceZoom = getDeviceZoom(); + x = DPIUtil.autoScaleUp(drawable, x, deviceZoom); + y = DPIUtil.autoScaleUp(drawable, y, deviceZoom); drawStringInPixels(string, x, y, isTransparent); } @@ -2209,8 +2221,9 @@ void drawStringInPixels (String string, int x, int y, boolean isTransparent) { * */ public void drawText (String string, int x, int y) { - x = DPIUtil.autoScaleUp(drawable, x); - y = DPIUtil.autoScaleUp(drawable, y); + int deviceZoom = getDeviceZoom(); + x = DPIUtil.autoScaleUp(drawable, x, deviceZoom); + y = DPIUtil.autoScaleUp(drawable, y, deviceZoom); drawTextInPixels(string, x, y); } @@ -2243,8 +2256,9 @@ void drawTextInPixels (String string, int x, int y) { * */ public void drawText (String string, int x, int y, boolean isTransparent) { - x = DPIUtil.autoScaleUp(drawable, x); - y = DPIUtil.autoScaleUp(drawable, y); + int deviceZoom = getDeviceZoom(); + x = DPIUtil.autoScaleUp(drawable, x, deviceZoom); + y = DPIUtil.autoScaleUp(drawable, y, deviceZoom); drawTextInPixels(string, x, y, isTransparent); } @@ -2294,8 +2308,9 @@ void drawTextInPixels (String string, int x, int y, boolean isTransparent) { * */ public void drawText (String string, int x, int y, int flags) { - x = DPIUtil.autoScaleUp(drawable, x); - y = DPIUtil.autoScaleUp(drawable, y); + int deviceZoom = getDeviceZoom(); + x = DPIUtil.autoScaleUp(drawable, x, deviceZoom); + y = DPIUtil.autoScaleUp(drawable, y, deviceZoom); drawTextInPixels(string, x, y, flags); } @@ -2673,10 +2688,11 @@ public boolean equals (Object object) { * @see #drawArc */ public void fillArc (int x, int y, int width, int height, int startAngle, int arcAngle) { - x = DPIUtil.autoScaleUp (drawable, x); - y = DPIUtil.autoScaleUp (drawable, y); - width = DPIUtil.autoScaleUp (drawable, width); - height = DPIUtil.autoScaleUp (drawable, height); + int deviceZoom = getDeviceZoom(); + x = DPIUtil.autoScaleUp (drawable, x, deviceZoom); + y = DPIUtil.autoScaleUp (drawable, y, deviceZoom); + width = DPIUtil.autoScaleUp (drawable, width, deviceZoom); + height = DPIUtil.autoScaleUp (drawable, height, deviceZoom); fillArcInPixels(x, y, width, height, startAngle, arcAngle); } @@ -2752,10 +2768,11 @@ void fillArcInPixels (int x, int y, int width, int height, int startAngle, int a * @see #drawRectangle(int, int, int, int) */ public void fillGradientRectangle (int x, int y, int width, int height, boolean vertical) { - x = DPIUtil.autoScaleUp (drawable, x); - y = DPIUtil.autoScaleUp (drawable, y); - width = DPIUtil.autoScaleUp (drawable, width); - height = DPIUtil.autoScaleUp (drawable, height); + int deviceZoom = getDeviceZoom(); + x = DPIUtil.autoScaleUp (drawable, x, deviceZoom); + y = DPIUtil.autoScaleUp (drawable, y, deviceZoom); + width = DPIUtil.autoScaleUp (drawable, width, deviceZoom); + height = DPIUtil.autoScaleUp (drawable, height, deviceZoom); fillGradientRectangleInPixels(x, y, width, height, vertical); } @@ -2870,10 +2887,11 @@ void fillGradientRectangleInPixels(int x, int y, int width, int height, boolean * @see #drawOval */ public void fillOval (int x, int y, int width, int height) { - x = DPIUtil.autoScaleUp (drawable, x); - y = DPIUtil.autoScaleUp (drawable, y); - width = DPIUtil.autoScaleUp (drawable, width); - height = DPIUtil.autoScaleUp (drawable, height); + int deviceZoom = getDeviceZoom(); + x = DPIUtil.autoScaleUp (drawable, x, deviceZoom); + y = DPIUtil.autoScaleUp (drawable, y, deviceZoom); + width = DPIUtil.autoScaleUp (drawable, width, deviceZoom); + height = DPIUtil.autoScaleUp (drawable, height, deviceZoom); fillOvalInPixels(x, y, width, height); } @@ -2943,7 +2961,7 @@ public void fillPath (Path path) { */ public void fillPolygon (int[] pointArray) { if (pointArray == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - fillPolygonInPixels(DPIUtil.autoScaleUp(drawable, pointArray)); + fillPolygonInPixels(DPIUtil.autoScaleUp(drawable, pointArray, getDeviceZoom())); } void fillPolygonInPixels (int[] pointArray) { @@ -2992,10 +3010,11 @@ void fillPolygonInPixels (int[] pointArray) { * @see #drawRectangle(int, int, int, int) */ public void fillRectangle (int x, int y, int width, int height) { - x = DPIUtil.autoScaleUp (drawable, x); - y = DPIUtil.autoScaleUp (drawable, y); - width = DPIUtil.autoScaleUp (drawable, width); - height = DPIUtil.autoScaleUp (drawable, height); + int deviceZoom = getDeviceZoom(); + x = DPIUtil.autoScaleUp (drawable, x, deviceZoom); + y = DPIUtil.autoScaleUp (drawable, y, deviceZoom); + width = DPIUtil.autoScaleUp (drawable, width, deviceZoom); + height = DPIUtil.autoScaleUp (drawable, height, deviceZoom); fillRectangleInPixels(x, y, width, height); } @@ -3035,7 +3054,7 @@ void fillRectangleInPixels (int x, int y, int width, int height) { */ public void fillRectangle (Rectangle rect) { if (rect == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - rect = DPIUtil.autoScaleUp(drawable, rect); + rect = DPIUtil.autoScaleUp(drawable, rect, getDeviceZoom()); fillRectangleInPixels(rect.x, rect.y, rect.width, rect.height); } @@ -3057,12 +3076,13 @@ public void fillRectangle (Rectangle rect) { * @see #drawRoundRectangle */ public void fillRoundRectangle (int x, int y, int width, int height, int arcWidth, int arcHeight) { - x = DPIUtil.autoScaleUp (drawable, x); - y = DPIUtil.autoScaleUp (drawable, y); - width = DPIUtil.autoScaleUp (drawable, width); - height = DPIUtil.autoScaleUp (drawable, height); - arcWidth = DPIUtil.autoScaleUp (drawable, arcWidth); - arcHeight = DPIUtil.autoScaleUp (drawable, arcHeight); + int deviceZoom = getDeviceZoom(); + x = DPIUtil.autoScaleUp (drawable, x, deviceZoom); + y = DPIUtil.autoScaleUp (drawable, y, deviceZoom); + width = DPIUtil.autoScaleUp (drawable, width, deviceZoom); + height = DPIUtil.autoScaleUp (drawable, height, deviceZoom); + arcWidth = DPIUtil.autoScaleUp (drawable, arcWidth, deviceZoom); + arcHeight = DPIUtil.autoScaleUp (drawable, arcHeight, deviceZoom); fillRoundRectangleInPixels(x, y, width, height, arcWidth, arcHeight); } @@ -3321,7 +3341,7 @@ public int getCharWidth(char ch) { * */ public Rectangle getClipping () { - return DPIUtil.autoScaleDown(drawable, getClippingInPixels()); + return DPIUtil.scaleDown(drawable, getClippingInPixels(), getDeviceZoom()); } Rectangle getClippingInPixels() { @@ -3579,9 +3599,10 @@ public int getInterpolation() { */ public LineAttributes getLineAttributes () { LineAttributes attributes = getLineAttributesInPixels(); - attributes.width = DPIUtil.autoScaleDown(drawable, attributes.width); + int deviceZoom = getDeviceZoom(); + attributes.width = DPIUtil.scaleDown(drawable, attributes.width, deviceZoom); if(attributes.dash != null) { - attributes.dash = DPIUtil.autoScaleDown(drawable, attributes.dash); + attributes.dash = DPIUtil.scaleDown(drawable, attributes.dash, deviceZoom); } return attributes; } @@ -3630,8 +3651,9 @@ public int[] getLineDash() { if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); if (data.lineDashes == null) return null; int[] lineDashes = new int[data.lineDashes.length]; + int deviceZoom = getDeviceZoom(); for (int i = 0; i < lineDashes.length; i++) { - lineDashes[i] = DPIUtil.autoScaleDown(drawable, (int)data.lineDashes[i]); + lineDashes[i] = DPIUtil.scaleDown(drawable, (int)data.lineDashes[i], deviceZoom); } return lineDashes; } @@ -3684,7 +3706,7 @@ public int getLineStyle() { * */ public int getLineWidth () { - return DPIUtil.autoScaleDown(drawable, getLineWidthInPixels()); + return DPIUtil.scaleDown(drawable, getLineWidthInPixels(), getDeviceZoom()); } int getLineWidthInPixels() { @@ -3905,6 +3927,9 @@ void init(Drawable drawable, GCData data, long hDC) { } else { data.font = Font.win32_new(device, OS.GetCurrentObject(hDC, OS.OBJ_FONT)); } + if (data.nativeZoom == 0) { + data.nativeZoom = extractZoom(hDC); + } Image image = data.image; if (image != null) { data.hNullBitmap = OS.SelectObject(hDC, image.handle); @@ -3924,6 +3949,16 @@ void init(Drawable drawable, GCData data, long hDC) { handle = hDC; } +private static int extractZoom(long hDC) { + long hwnd = OS.WindowFromDC(hDC); + long parentWindow = OS.GetAncestor(hwnd, OS.GA_ROOT); + long monitorParent = OS.MonitorFromWindow(parentWindow, OS.MONITOR_DEFAULTTONEAREST); + int [] dpiX = new int[1]; + int [] dpiY = new int[1]; + int result = OS.GetDpiForMonitor (monitorParent, OS.MDT_EFFECTIVE_DPI, dpiX, dpiY); + return (result == OS.S_OK) ? DPIUtil.mapDPIToZoom (dpiX[0]) : DPIUtil.getNativeDeviceZoom(); +} + /** * Returns an integer hash code for the receiver. Any two * objects that return true when passed to @@ -4242,10 +4277,11 @@ void setClipping(long clipRgn) { * */ public void setClipping (int x, int y, int width, int height) { - x = DPIUtil.autoScaleUp(drawable, x); - y = DPIUtil.autoScaleUp(drawable, y); - width = DPIUtil.autoScaleUp(drawable, width); - height = DPIUtil.autoScaleUp(drawable, height); + int deviceZoom = getDeviceZoom(); + x = DPIUtil.autoScaleUp(drawable, x, deviceZoom); + y = DPIUtil.autoScaleUp(drawable, y, deviceZoom); + width = DPIUtil.autoScaleUp(drawable, width, deviceZoom); + height = DPIUtil.autoScaleUp(drawable, height, deviceZoom); setClippingInPixels(x, y, width, height); } @@ -4313,7 +4349,7 @@ public void setClipping (Rectangle rect) { setClipping(0); } else { - rect = DPIUtil.autoScaleUp(drawable, rect); + rect = DPIUtil.autoScaleUp(drawable, rect, getDeviceZoom()); setClippingInPixels(rect.x, rect.y, rect.width, rect.height); } } @@ -4386,7 +4422,7 @@ public void setFillRule(int rule) { public void setFont (Font font) { if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); if (font != null && font.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); - data.font = font != null ? Font.win32_new(font, DPIUtil.getNativeDeviceZoom()) : data.device.systemFont; + data.font = font != null ? Font.win32_new(font, getNativeDeviceZoom()) : data.device.systemFont; data.state &= ~FONT; } @@ -4519,7 +4555,7 @@ public void setInterpolation(int interpolation) { */ public void setLineAttributes (LineAttributes attributes) { if (attributes == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); - attributes.width = DPIUtil.autoScaleUp(drawable, attributes.width); + attributes.width = DPIUtil.autoScaleUp(drawable, attributes.width, getDeviceZoom()); setLineAttributesInPixels(attributes); } @@ -4582,8 +4618,9 @@ void setLineAttributesInPixels (LineAttributes attributes) { } if (changed) { float[] newDashes = new float[dashes.length]; + int deviceZoom = getDeviceZoom(); for (int i = 0; i < newDashes.length; i++) { - newDashes[i] = DPIUtil.autoScaleUp(drawable, dashes[i]); + newDashes[i] = DPIUtil.autoScaleUp(drawable, dashes[i], deviceZoom); } dashes = newDashes; mask |= LINE_STYLE; @@ -4671,9 +4708,10 @@ public void setLineDash(int[] dashes) { if (dashes != null && dashes.length > 0) { boolean changed = data.lineStyle != SWT.LINE_CUSTOM || lineDashes == null || lineDashes.length != dashes.length; float[] newDashes = new float[dashes.length]; + int deviceZoom = getDeviceZoom(); for (int i = 0; i < dashes.length; i++) { if (dashes[i] <= 0) SWT.error(SWT.ERROR_INVALID_ARGUMENT); - newDashes[i] = DPIUtil.autoScaleUp(drawable, (float) dashes[i]); + newDashes[i] = DPIUtil.autoScaleUp(drawable, (float) dashes[i], deviceZoom); if (!changed && lineDashes[i] != newDashes[i]) changed = true; } if (!changed) return; @@ -4774,7 +4812,7 @@ public void setLineStyle(int lineStyle) { * */ public void setLineWidth(int lineWidth) { - lineWidth = DPIUtil.autoScaleUp (drawable, lineWidth); + lineWidth = DPIUtil.autoScaleUp (drawable, lineWidth, getDeviceZoom()); setLineWidthInPixels(lineWidth); } @@ -4920,7 +4958,7 @@ public void setTransform(Transform transform) { */ public Point stringExtent (String string) { if (string == null) SWT.error (SWT.ERROR_NULL_ARGUMENT); - return DPIUtil.autoScaleDown(drawable, stringExtentInPixels(string)); + return DPIUtil.scaleDown(drawable, stringExtentInPixels(string), getDeviceZoom()); } Point stringExtentInPixels (String string) { @@ -4965,7 +5003,7 @@ Point stringExtentInPixels (String string) { * */ public Point textExtent (String string) { - return DPIUtil.autoScaleDown(drawable, textExtentInPixels(string, SWT.DRAW_DELIMITER | SWT.DRAW_TAB)); + return DPIUtil.scaleDown(drawable, textExtentInPixels(string, SWT.DRAW_DELIMITER | SWT.DRAW_TAB), getDeviceZoom()); } /** @@ -5000,7 +5038,7 @@ public Point textExtent (String string) { * */ public Point textExtent (String string, int flags) { - return DPIUtil.autoScaleDown(drawable, textExtentInPixels(string, flags)); + return DPIUtil.scaleDown(drawable, textExtentInPixels(string, flags), getDeviceZoom()); } Point textExtentInPixels(String string, int flags) { @@ -5120,4 +5158,12 @@ private static int sin(int angle, int length) { return (int)(Math.sin(angle * (Math.PI/180)) * length); } +private int getNativeDeviceZoom() { + return data.nativeZoom != 0 ? data.nativeZoom : DPIUtil.getNativeDeviceZoom(); +} + +private int getDeviceZoom() { + return DPIUtil.getZoomForAutoscaleProperty(getNativeDeviceZoom()); +} + } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GCData.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GCData.java index fa177db2c83..3dd5a16b24a 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GCData.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/GCData.java @@ -47,6 +47,7 @@ public final class GCData { public float[] lineDashes; public float lineMiterLimit = 10; public int alpha = 0xFF; + public int nativeZoom; public Image image; public PAINTSTRUCT ps; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java index 301323aa9ec..1898adbdfe1 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/graphics/Image.java @@ -2154,6 +2154,7 @@ public long internal_new_GC (GCData data) { data.style |= SWT.LEFT_TO_RIGHT; } data.device = device; + data.nativeZoom = currentNativeZoom; data.image = this; data.font = Font.win32_new(device.getSystemFont(), DPIUtil.getNativeDeviceZoom()); } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java index 60511ea33b2..910b5cf7a22 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Button.java @@ -1375,7 +1375,7 @@ LRESULT wmNotifyChild (NMHDR hdr, long wParam, long lParam) { if (image != null) { GCData data = new GCData(); data.device = display; - GC gc = GC.win32_new (nmcd.hdc, data); + GC gc = createNewGC(nmcd.hdc, data); int margin = computeLeftMargin(); Rectangle imageBounds = DPIUtil.autoScaleBounds(image.getBounds(), this.getZoom(), 100); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Composite.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Composite.java index 47b6d9fa997..d3782e8803f 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Composite.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Composite.java @@ -1533,7 +1533,7 @@ LRESULT WM_PAINT (long wParam, long lParam) { OS.SetRect (rect, ps.left, ps.top, ps.right, ps.bottom); drawBackground (phdc [0], rect); } - GC gc = GC.win32_new (phdc [0], data); + GC gc = createNewGC(phdc [0], data); Event event = new Event (); event.gc = gc; event.setBoundsInPixels(new Rectangle(ps.left, ps.top, width, height)); @@ -1697,7 +1697,7 @@ LRESULT WM_PRINTCLIENT (long wParam, long lParam) { data.background = control.getBackgroundPixel (); data.font = Font.win32_new(display, OS.SendMessage (handle, OS.WM_GETFONT, 0, 0)); data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); - GC gc = GC.win32_new (wParam, data); + GC gc = createNewGC(wParam, data); Event event = new Event (); event.gc = gc; event.setBoundsInPixels(new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top)); 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 3241f80b19d..4857cc02969 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 @@ -1742,6 +1742,7 @@ public long internal_new_GC (GCData data) { } } data.device = display; + data.nativeZoom = nativeZoom; int foreground = getForegroundPixel (); if (foreground != OS.GetTextColor (hDC)) data.foreground = foreground; Control control = findBackgroundControl (); 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 c94d7cfd68e..2084db4100d 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 @@ -2748,6 +2748,7 @@ public long internal_new_GC (GCData data) { } else { data.style |= SWT.LEFT_TO_RIGHT; } + data.nativeZoom = getPrimaryMonitor().getZoom(); data.device = this; data.font = getSystemFont (); } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ExpandBar.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ExpandBar.java index 58535cc13c1..3fc7f84b441 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ExpandBar.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/ExpandBar.java @@ -807,7 +807,7 @@ LRESULT WM_PRINTCLIENT (long wParam, long lParam) { GCData data = new GCData (); data.device = display; data.foreground = getForegroundPixel (); - GC gc = GC.win32_new (wParam, data); + GC gc = createNewGC(wParam, data); drawWidget (gc, rect); gc.dispose (); return result; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Label.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Label.java index 4265a2eb6a4..c99bb3288fd 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Label.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Label.java @@ -564,7 +564,7 @@ void wmDrawChildImage(DRAWITEMSTRUCT struct) { GCData data = new GCData(); data.device = display; - GC gc = GC.win32_new (struct.hDC, data); + GC gc = createNewGC(struct.hDC, data); Image image = getEnabled () ? this.image : new Image (display, this.image, SWT.IMAGE_DISABLE); gc.drawImage (image, DPIUtil.autoScaleDown(x), DPIUtil.autoScaleDown(Math.max (0, (height - imageRect.height) / 2))); if (image != this.image) image.dispose (); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/MenuItem.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/MenuItem.java index 17fa412c6f2..ad469ed53de 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/MenuItem.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/MenuItem.java @@ -1126,7 +1126,7 @@ LRESULT wmDrawChild (long wParam, long lParam) { if (image != null) { GCData data = new GCData(); data.device = display; - GC gc = GC.win32_new (struct.hDC, data); + GC gc = createNewGC(struct.hDC, data); /* * Bug in Windows. When a bitmap is included in the * menu bar, the HDC seems to already include the left diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java index f4739b8b6f6..c392a6833b6 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Table.java @@ -3464,7 +3464,7 @@ void sendEraseItemEvent (TableItem item, NMLVCUSTOMDRAW nmcd, long lParam, Event data.font = item.getFont (nmcd.iSubItem); data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); int nSavedDC = OS.SaveDC (hDC); - GC gc = GC.win32_new (hDC, data); + GC gc = createNewGC(hDC, data); RECT cellRect = item.getBounds ((int)nmcd.dwItemSpec, nmcd.iSubItem, true, true, true, true, hDC); Event event = new Event (); event.item = item; @@ -3599,7 +3599,7 @@ Event sendEraseItemEvent (TableItem item, NMTTCUSTOMDRAW nmcd, int column, RECT data.background = OS.GetBkColor (nmcd.hdc); data.font = item.getFont (column); data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); - GC gc = GC.win32_new (nmcd.hdc, data); + GC gc = createNewGC(nmcd.hdc, data); Event event = new Event (); event.item = item; event.index = column; @@ -3620,7 +3620,7 @@ Event sendMeasureItemEvent (TableItem item, int row, int column, long hDC) { data.device = display; data.font = item.getFont (column); int nSavedDC = OS.SaveDC (hDC); - GC gc = GC.win32_new (hDC, data); + GC gc = createNewGC(hDC, data); RECT itemRect = item.getBounds (row, column, true, true, false, false, hDC); Event event = new Event (); event.item = item; @@ -3907,7 +3907,7 @@ void sendPaintItemEvent (TableItem item, NMLVCUSTOMDRAW nmcd) { } data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); int nSavedDC = OS.SaveDC (hDC); - GC gc = GC.win32_new (hDC, data); + GC gc = createNewGC(hDC, data); RECT itemRect = item.getBounds ((int)nmcd.dwItemSpec, nmcd.iSubItem, true, true, false, false, hDC); Event event = new Event (); event.item = item; @@ -3948,7 +3948,7 @@ Event sendPaintItemEvent (TableItem item, NMTTCUSTOMDRAW nmcd, int column, RECT data.foreground = OS.GetTextColor (nmcd.hdc); data.background = OS.GetBkColor (nmcd.hdc); data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); - GC gc = GC.win32_new (nmcd.hdc, data); + GC gc = createNewGC(nmcd.hdc, data); Event event = new Event (); event.item = item; event.index = column; @@ -6964,7 +6964,7 @@ LRESULT wmNotifyHeader (NMHDR hdr, long wParam, long lParam) { if (columns[i].image != null) { GCData data = new GCData(); data.device = display; - GC gc = GC.win32_new (nmcd.hdc, data); + GC gc = createNewGC(nmcd.hdc, data); int y = Math.max (0, (nmcd.bottom - columns[i].image.getBoundsInPixels().height) / 2); gc.drawImage (columns[i].image, DPIUtil.autoScaleDown(x), DPIUtil.autoScaleDown(y)); x += columns[i].image.getBoundsInPixels().width + 12; @@ -7286,7 +7286,7 @@ LRESULT wmNotifyToolTip (NMTTCUSTOMDRAW nmcd, long lParam) { data.foreground = OS.GetTextColor (nmcd.hdc); data.background = OS.GetBkColor (nmcd.hdc); data.font = Font.win32_new (display, hFont); - GC gc = GC.win32_new (nmcd.hdc, data); + GC gc = createNewGC(nmcd.hdc, data); int x = cellRect.left; if (pinfo.iSubItem != 0) x -= gridWidth; Image image = item.getImage (pinfo.iSubItem); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java index 5be47a3123f..464c0ab2678 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java @@ -527,7 +527,7 @@ LRESULT CDDS_ITEMPOSTPAINT (NMTVCUSTOMDRAW nmcd, long wParam, long lParam) { if (!ignoreDrawForeground) { GCData data = new GCData(); data.device = display; - GC gc = GC.win32_new (hDC, data); + GC gc = createNewGC(hDC, data); RECT iconRect = item.getBounds (index, false, true, false, false, true, hDC); // Pixels gc.setClipping (DPIUtil.autoScaleDown(new Rectangle(iconRect.left, iconRect.top, iconRect.right - iconRect.left, iconRect.bottom - iconRect.top))); gc.drawImage (image, 0, 0, bounds.width, bounds.height, DPIUtil.autoScaleDown(iconRect.left), DPIUtil.autoScaleDown(iconRect.top), size.x, size.y); @@ -625,7 +625,7 @@ LRESULT CDDS_ITEMPOSTPAINT (NMTVCUSTOMDRAW nmcd, long wParam, long lParam) { } data.font = item.getFont (index); data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); - GC gc = GC.win32_new (hDC, data); + GC gc = createNewGC(hDC, data); Event event = new Event (); event.item = item; event.index = index; @@ -768,7 +768,7 @@ LRESULT CDDS_ITEMPOSTPAINT (NMTVCUSTOMDRAW nmcd, long wParam, long lParam) { int x1 = Math.max (rect.left, rect.left - inset + 1); GCData data = new GCData(); data.device = display; - GC gc = GC.win32_new (hDC, data); + GC gc = createNewGC(hDC, data); gc.setClipping (DPIUtil.autoScaleDown(new Rectangle(x1, rect.top, rect.right - x1, rect.bottom - rect.top))); gc.drawImage (image, 0, 0, bounds.width, bounds.height, DPIUtil.autoScaleDown(x1), DPIUtil.autoScaleDown(y1), size.x, size.y); OS.SelectClipRgn (hDC, 0); @@ -841,7 +841,7 @@ LRESULT CDDS_ITEMPOSTPAINT (NMTVCUSTOMDRAW nmcd, long wParam, long lParam) { if (clrTextBk != -1) data.background = clrTextBk; } data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); - GC gc = GC.win32_new (hDC, data); + GC gc = createNewGC(hDC, data); Event event = new Event (); event.item = item; event.index = index; @@ -1063,7 +1063,7 @@ LRESULT CDDS_ITEMPREPAINT (NMTVCUSTOMDRAW nmcd, long wParam, long lParam) { } data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); data.font = item.getFont (index); - GC gc = GC.win32_new (hDC, data); + GC gc = createNewGC(hDC, data); Event event = new Event (); event.index = index; event.item = item; @@ -4523,7 +4523,7 @@ Event sendEraseItemEvent (TreeItem item, NMTTCUSTOMDRAW nmcd, int column, RECT c data.background = OS.GetBkColor (nmcd.hdc); data.font = item.getFont (column); data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); - GC gc = GC.win32_new (nmcd.hdc, data); + GC gc = createNewGC(nmcd.hdc, data); Event event = new Event (); event.item = item; event.index = column; @@ -4545,7 +4545,7 @@ Event sendMeasureItemEvent (TreeItem item, int index, long hDC, int detail) { GCData data = new GCData (); data.device = display; data.font = item.getFont (index); - GC gc = GC.win32_new (hDC, data); + GC gc = createNewGC(hDC, data); Event event = new Event (); event.item = item; event.gc = gc; @@ -4579,7 +4579,7 @@ Event sendPaintItemEvent (TreeItem item, NMTTCUSTOMDRAW nmcd, int column, RECT i data.foreground = OS.GetTextColor (nmcd.hdc); data.background = OS.GetBkColor (nmcd.hdc); data.uiState = (int)OS.SendMessage (handle, OS.WM_QUERYUISTATE, 0, 0); - GC gc = GC.win32_new (nmcd.hdc, data); + GC gc = createNewGC(nmcd.hdc, data); Event event = new Event (); event.item = item; event.index = column; @@ -7925,7 +7925,7 @@ LRESULT wmNotifyHeader (NMHDR hdr, long wParam, long lParam) { if (columns[i].image != null) { GCData data = new GCData(); data.device = display; - GC gc = GC.win32_new (nmcd.hdc, data); + GC gc = createNewGC(nmcd.hdc, data); Rectangle imageBounds = DPIUtil.autoScaleBounds(columns[i].image.getBounds(), this.getZoom(), 100); int y = Math.max (0, (nmcd.bottom - imageBounds.height) / 2); gc.drawImage (columns[i].image, DPIUtil.autoScaleDown(x), DPIUtil.autoScaleDown(y)); @@ -8214,7 +8214,7 @@ LRESULT wmNotifyToolTip (NMTTCUSTOMDRAW nmcd, long lParam) { data.foreground = OS.GetTextColor (nmcd.hdc); data.background = OS.GetBkColor (nmcd.hdc); data.font = Font.win32_new (display, hFont); - GC gc = GC.win32_new (nmcd.hdc, data); + GC gc = createNewGC(nmcd.hdc, data); int x = cellRect [0].left + INSET; if (index [0] != 0) x -= gridWidth; Image image = item [0].getImage (index [0]); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Widget.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Widget.java index efb713a0019..c21b3d6aaa6 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Widget.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Widget.java @@ -2647,6 +2647,11 @@ void notifyDisposalTracker() { } } +GC createNewGC(long hDC, GCData data) { + data.nativeZoom = nativeZoom; + return GC.win32_new(hDC, data); +} + int getZoom() { return DPIUtil.getZoomForAutoscaleProperty(nativeZoom); } diff --git a/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/graphics/GCWin32Tests.java b/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/graphics/GCWin32Tests.java new file mode 100644 index 00000000000..8e4a59bacb1 --- /dev/null +++ b/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/graphics/GCWin32Tests.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2024 Yatta Solutions + * + * 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 static org.junit.Assert.assertEquals; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.internal.DPITestUtil; +import org.eclipse.swt.internal.DPIUtil; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Shell; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class GCWin32Tests { + private Display display; + private boolean autoScaleOnRuntime; + + @Before + public void setUp() { + autoScaleOnRuntime = DPIUtil.isAutoScaleOnRuntimeActive(); + DPITestUtil.setAutoScaleOnRunTime(true); + display = Display.getDefault(); + } + + @After + public void tearDown() { + DPITestUtil.setAutoScaleOnRunTime(autoScaleOnRuntime); + } + + @Test + public void gcZoomLevelMustChangeOnShellZoomChange() { + CompletableFuture gcNativeZoom = new CompletableFuture<>(); + CompletableFuture scaledGcNativeZoom = new CompletableFuture<>(); + int zoom = DPIUtil.getDeviceZoom(); + AtomicBoolean isScaled = new AtomicBoolean(false); + Shell shell = new Shell(display); + shell.addListener(SWT.Paint, event -> { + if (isScaled.get()) { + scaledGcNativeZoom.complete(event.gc.getGCData().nativeZoom); + } else { + gcNativeZoom.complete(event.gc.getGCData().nativeZoom); + } + }); + + shell.open(); + assertEquals("GCData must have a zoom level equal to the actual zoom level of the widget/shell", DPIUtil.getNativeDeviceZoom(), (int) gcNativeZoom.join()); + + int newSWTZoom = zoom * 2; + Event swtEvent = new Event(); + swtEvent.type = SWT.ZoomChanged; + swtEvent.widget = shell; + swtEvent.detail = newSWTZoom; + shell.notifyListeners(SWT.ZoomChanged, swtEvent); + isScaled.set(true); + shell.setVisible(false); + shell.setVisible(true); + + assertEquals("GCData must have a zoom level equal to the actual zoom level of the widget/shell on zoomChanged event", newSWTZoom, (int) scaledGcNativeZoom.join()); + } + + @Test + public void drawnElementsShouldScaleUpToTheRightZoomLevel() { + int zoom = DPIUtil.getDeviceZoom(); + int scalingFactor = 2; + Shell shell = new Shell(display); + GC gc = GC.win32_new(shell, new GCData()); + gc.getGCData().nativeZoom = zoom * scalingFactor; + gc.getGCData().lineWidth = 10; + assertEquals("DPIUtil calls with getDeviceZoom should scale to the right value", gc.getGCData().lineWidth, gc.getLineWidth() * scalingFactor, 0); + } +} diff --git a/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/internal/DPITestUtil.java b/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/internal/DPITestUtil.java new file mode 100644 index 00000000000..aece0d7b650 --- /dev/null +++ b/tests/org.eclipse.swt.tests.win32/JUnit Tests/org/eclipse/swt/internal/DPITestUtil.java @@ -0,0 +1,9 @@ +package org.eclipse.swt.internal; + +public class DPITestUtil { + + public static void setAutoScaleOnRunTime(boolean value) { + DPIUtil.setAutoScaleOnRuntimeActive(value); + } + +}