From 75d4a478affd7a2fd4abfa698aaf754757fafea9 Mon Sep 17 00:00:00 2001 From: Heiko Klare Date: Fri, 8 Aug 2025 16:02:46 +0200 Subject: [PATCH] [Win32] Fix drag and drop without monitor-specific scaling #2394 To fix drag and drop behavior on multiple monitors with different zooms when using monitor-specific scaling, a recent change adapted the OS callbacks for drop operations to run with the required DPI awareness (PerMonitorV2) in that case. This change did not consider that without monitor-specific scaling (and particularly when DPI awareness "System" is used), running with that modified DPI awareness is not correct. This change adapts the drop callback to only adapt the DPI awareness if appropriate (i.e., if monitor-specific scaling is enabled). Fixes https://github.com/eclipse-platform/eclipse.platform.swt/issues/2394 --- .../win32/org/eclipse/swt/dnd/DropTarget.java | 6 +++--- .../eclipse/swt/internal/Win32DPIUtils.java | 8 ++++++-- .../win32/org/eclipse/swt/widgets/Display.java | 18 +++++------------- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/win32/org/eclipse/swt/dnd/DropTarget.java b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/win32/org/eclipse/swt/dnd/DropTarget.java index 190dda12f23..b5a91a507d9 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/win32/org/eclipse/swt/dnd/DropTarget.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Drag and Drop/win32/org/eclipse/swt/dnd/DropTarget.java @@ -242,7 +242,7 @@ void createCOMInterfaces() { public long method2(long[] args) {return Release();} @Override public long method3(long[] args) { - return Win32DPIUtils.runWithProperDPIAwareness(() -> { + return Win32DPIUtils.runWithProperDPIAwareness(getDisplay(), () -> { if (args.length == 5) { return DragEnter(args[0], (int)args[1], (int)args[2], (int)args[3], args[4]); } else { @@ -252,7 +252,7 @@ public long method3(long[] args) { } @Override public long method4(long[] args) { - return Win32DPIUtils.runWithProperDPIAwareness(() -> { + return Win32DPIUtils.runWithProperDPIAwareness(getDisplay(), () -> { if (args.length == 4) { return DragOver((int)args[0], (int)args[1], (int)args[2], args[3]); } else { @@ -264,7 +264,7 @@ public long method4(long[] args) { public long method5(long[] args) {return DragLeave();} @Override public long method6(long[] args) { - return Win32DPIUtils.runWithProperDPIAwareness(() -> { + return Win32DPIUtils.runWithProperDPIAwareness(getDisplay(), () -> { if (args.length == 5) { return Drop(args[0], (int)args[1], (int)args[2], (int)args[3], args[4]); } else { diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/Win32DPIUtils.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/Win32DPIUtils.java index 86326e7193a..a15cf2cecdc 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/Win32DPIUtils.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/Win32DPIUtils.java @@ -19,6 +19,7 @@ import org.eclipse.swt.graphics.*; import org.eclipse.swt.internal.win32.*; import org.eclipse.swt.internal.win32.version.*; +import org.eclipse.swt.widgets.*; /** * This class is used in the win32 implementation only to provide @@ -68,8 +69,11 @@ public static boolean setDPIAwareness(int desiredDpiAwareness) { return true; } - public static T runWithProperDPIAwareness(Supplier operation) { - // refreshing is only necessary, when monitor specific scaling is active + public static T runWithProperDPIAwareness(Display display, Supplier operation) { + // only with monitor-specific scaling enabled, the main thread's DPI awareness may be adapted + if (!display.isRescalingAtRuntime()) { + return operation.get(); + } long previousDPIAwareness = OS.GetThreadDpiAwarenessContext(); try { if (!setDPIAwareness(OS.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)) { 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 1ce5dbc2152..54747b9d9cf 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 @@ -1461,7 +1461,7 @@ public Widget findWidget (Widget widget, long id) { long foregroundIdleProc (long code, long wParam, long lParam) { if (code >= 0) { - Runnable processMessages = () -> { + Supplier processMessages = () -> { sendPostExternalEventDispatchEvent (); if (runMessagesInIdle) { if (runMessagesInMessageProc) { @@ -1487,6 +1487,7 @@ long foregroundIdleProc (long code, long wParam, long lParam) { int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT; if (!OS.PeekMessage (msg, 0, 0, 0, flags)) wakeThread (); sendPreExternalEventDispatchEvent (); + return true; }; if (!synchronizer.isMessagesEmpty()) { // Windows hooks will inherit the thread DPI awareness from @@ -1495,7 +1496,7 @@ long foregroundIdleProc (long code, long wParam, long lParam) { // This requires to reset the thread DPi awareness to make // sure, all UI updates caused by this will be executed // with the correct DPI awareness - runWithProperDPIAwareness(processMessages); + Win32DPIUtils.runWithProperDPIAwareness(this, processMessages); } } return OS.CallNextHookEx (idleHook, (int)code, wParam, lParam); @@ -3478,10 +3479,11 @@ long msgFilterProc (long code, long wParam, long lParam) { // This requires to reset the thread DPi awareness to make // sure, all UI updates caused by this will be executed // with the correct DPI awareness - runWithProperDPIAwareness(() -> { + Win32DPIUtils.runWithProperDPIAwareness(this, () -> { if (!OS.PeekMessage (msg, 0, 0, 0, flags)) { if (runAsyncMessages (false)) wakeThread (); } + return true; }); } break; @@ -5414,14 +5416,4 @@ private boolean setMonitorSpecificScaling(boolean activate) { return false; } -private void runWithProperDPIAwareness(Runnable operation) { - if (isRescalingAtRuntime()) { - Win32DPIUtils.runWithProperDPIAwareness(() -> { - operation.run(); - return true; - }); - } else { - operation.run(); - } -} }