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 b2e59a8c70f..08801e4af4a 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 @@ -8470,6 +8470,22 @@ JNIEXPORT jlong JNICALL OS_NATIVE(SendMessage__JI_3I_3I) } #endif +#ifndef NO_SendMessageCallback +JNIEXPORT jlong JNICALL OS_NATIVE(SendMessageCallback) + (JNIEnv *env, jclass that, jlong arg0, jint arg1, jlong arg2, jcharArray arg3, jlong arg4, jlong arg5) +{ + jchar *lparg3=NULL; + jlong rc = 0; + OS_NATIVE_ENTER(env, that, SendMessageCallback_FUNC); + if (arg3) if ((lparg3 = (*env)->GetCharArrayElements(env, arg3, NULL)) == NULL) goto fail; + rc = (jlong)SendMessageCallback((HWND)arg0, arg1, (WPARAM)arg2, (LPARAM)lparg3, (SENDASYNCPROC)arg4, (LONG_PTR)arg5); +fail: + if (arg3 && lparg3) (*env)->ReleaseCharArrayElements(env, arg3, lparg3, 0); + OS_NATIVE_EXIT(env, that, SendMessageCallback_FUNC); + return rc; +} +#endif + #ifndef NO_SetActiveWindow JNIEXPORT jlong JNICALL OS_NATIVE(SetActiveWindow) (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 15503f2c022..38da4b116ed 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 @@ -625,6 +625,7 @@ typedef enum { SendMessage__JIJ_3C_FUNC, SendMessage__JIJ_3I_FUNC, SendMessage__JI_3I_3I_FUNC, + SendMessageCallback_FUNC, SetActiveWindow_FUNC, SetBkColor_FUNC, SetBkMode_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 798c7bf9ec4..94f735b5013 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 @@ -4113,6 +4113,14 @@ public static int HRESULT_FROM_WIN32(int x) { * @param lParam cast=(LPARAM) */ public static final native long SendMessage (long hWnd, int Msg, long wParam, char [] lParam); +/** + * @param hWnd cast=(HWND) + * @param wParam cast=(WPARAM) + * @param lParam cast=(LPARAM) + * @param lpResultCallBack cast=(SENDASYNCPROC) + * @param dwData cast=(LONG_PTR) + */ +public static final native long SendMessageCallback(long hWnd, int Msg, long wParam, char [] lParam, long lpResultCallBack, long dwData); /** * @param hWnd cast=(HWND) * @param wParam cast=(WPARAM) 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 59ba774fc48..8e28dd0a95a 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 @@ -16,6 +16,7 @@ import java.util.*; +import java.util.concurrent.*; import java.util.concurrent.atomic.*; import java.util.stream.*; @@ -5979,9 +5980,34 @@ LRESULT wmScrollChild (long wParam, long lParam) { return null; } +private class DPIChangeOperation { + Runnable operation; + Callback callback; + + DPIChangeOperation(Runnable operation) { + this.operation = operation; + } + + void asyncExec() { + callback = new Callback(this, "runAsyncOperation", 0); + OS.SendMessageCallback(Control.this.handle, OS.WM_NULL, 0, null, callback.getAddress(), 0); + } + + void syncExec() { + operation.run(); + } + + long runAsyncOperation() { + operation.run(); + callback.dispose(); + return 0; + } +} + static class DPIChangeExecution { AtomicInteger taskCount = new AtomicInteger(); private boolean asyncExec = true; + ExecutorService executor = Executors.newSingleThreadExecutor(); private void process(Control control, Runnable operation) { boolean currentAsyncExec = asyncExec; @@ -5991,10 +6017,11 @@ private void process(Control control, Runnable operation) { // to wrong results, because no final layout will be triggered asyncExec &= (comp.layout != null); } + DPIChangeOperation dpiChangeOperation = control.new DPIChangeOperation(operation); if (asyncExec) { - control.getDisplay().asyncExec(operation::run); + dpiChangeOperation.asyncExec(); } else { - operation.run(); + dpiChangeOperation.syncExec(); } // resetting it prevents to break asynchronous execution when the synchronous // DPI change handling is finished