Skip to content

Commit 918acf9

Browse files
committed
[win32] Refresh thread dpi awareness on hooks
This commit resets the DPI awareness for the WH_MSGFILTER hook, if called. For performance reasons that is only done, when runAsyncMessages will be triggered, as this can cause UI updates, which would be executed with the wrong DPI awareness context and cause UI glitches.
1 parent b4fabe5 commit 918acf9

File tree

1 file changed

+55
-25
lines changed
  • bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets

1 file changed

+55
-25
lines changed

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Display.java

Lines changed: 55 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1456,31 +1456,39 @@ public Widget findWidget (Widget widget, long id) {
14561456
long foregroundIdleProc (long code, long wParam, long lParam) {
14571457
if (code >= 0) {
14581458
if (!synchronizer.isMessagesEmpty()) {
1459-
sendPostExternalEventDispatchEvent ();
1460-
if (runMessagesInIdle) {
1461-
if (runMessagesInMessageProc) {
1462-
OS.PostMessage (hwndMessage, SWT_RUNASYNC, 0, 0);
1463-
} else {
1464-
runAsyncMessages (false);
1459+
// Windows hooks will inherit the thread DPI awareness from
1460+
// the process. Whatever DPI awareness was set before on
1461+
// the thread will be overwritten before the hook is called.
1462+
// This requires to reset the thread DPi awareness to make
1463+
// sure, all UI updates caused by this will be executed
1464+
// with the correct DPI awareness
1465+
runWithProperDPIAwareness(() -> {
1466+
sendPostExternalEventDispatchEvent ();
1467+
if (runMessagesInIdle) {
1468+
if (runMessagesInMessageProc) {
1469+
OS.PostMessage (hwndMessage, SWT_RUNASYNC, 0, 0);
1470+
} else {
1471+
runAsyncMessages (false);
1472+
}
14651473
}
1466-
}
1467-
/*
1468-
* Bug in Windows. For some reason, input events can be lost
1469-
* when a message is posted to the queue from a foreground idle
1470-
* hook. The fix is to detect that there are outstanding input
1471-
* events and avoid posting the wake event.
1472-
*
1473-
* Note that PeekMessage() changes the state of events on the
1474-
* queue to no longer be considered new. If we peek for input
1475-
* events and posted messages (PM_QS_INPUT | PM_QS_POSTMESSAGE),
1476-
* it is possible to cause WaitMessage() to sleep until a new
1477-
* input event is generated causing sync runnables not to be
1478-
* executed.
1479-
*/
1480-
MSG msg = new MSG();
1481-
int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT;
1482-
if (!OS.PeekMessage (msg, 0, 0, 0, flags)) wakeThread ();
1483-
sendPreExternalEventDispatchEvent ();
1474+
/*
1475+
* Bug in Windows. For some reason, input events can be lost
1476+
* when a message is posted to the queue from a foreground idle
1477+
* hook. The fix is to detect that there are outstanding input
1478+
* events and avoid posting the wake event.
1479+
*
1480+
* Note that PeekMessage() changes the state of events on the
1481+
* queue to no longer be considered new. If we peek for input
1482+
* events and posted messages (PM_QS_INPUT | PM_QS_POSTMESSAGE),
1483+
* it is possible to cause WaitMessage() to sleep until a new
1484+
* input event is generated causing sync runnables not to be
1485+
* executed.
1486+
*/
1487+
MSG msg = new MSG();
1488+
int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT;
1489+
if (!OS.PeekMessage (msg, 0, 0, 0, flags)) wakeThread ();
1490+
sendPreExternalEventDispatchEvent ();
1491+
});
14841492
}
14851493
}
14861494
return OS.CallNextHookEx (idleHook, (int)code, wParam, lParam);
@@ -3425,7 +3433,15 @@ long msgFilterProc (long code, long wParam, long lParam) {
34253433
MSG msg = new MSG ();
34263434
int flags = OS.PM_NOREMOVE | OS.PM_NOYIELD | OS.PM_QS_INPUT | OS.PM_QS_POSTMESSAGE;
34273435
if (!OS.PeekMessage (msg, 0, 0, 0, flags)) {
3428-
if (runAsyncMessages (false)) wakeThread ();
3436+
// Windows hooks will inherit the thread DPI awareness from
3437+
// the process. Whatever DPI awareness was set before on
3438+
// the thread will be overwritten before the hook is called.
3439+
// This requires to reset the thread DPi awareness to make
3440+
// sure, all UI updates caused by this will be executed
3441+
// with the correct DPI awareness
3442+
runWithProperDPIAwareness(() -> {
3443+
if (runAsyncMessages (false)) wakeThread ();
3444+
});
34293445
}
34303446
}
34313447
break;
@@ -5382,4 +5398,18 @@ private boolean setDPIAwareness(int desiredDpiAwareness) {
53825398
return true;
53835399
}
53845400

5401+
private void runWithProperDPIAwareness(Runnable operation) {
5402+
if (isRescalingAtRuntime()) {
5403+
// refreshing is only necessary, when monitor specific scaling is active
5404+
long previousDPIAwareness = OS.GetThreadDpiAwarenessContext();
5405+
if (!setDPIAwareness(OS.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)) {
5406+
// awareness was not changed, so no need to reset it
5407+
previousDPIAwareness = 0;
5408+
}
5409+
operation.run();
5410+
if (previousDPIAwareness > 0) {
5411+
OS.SetThreadDpiAwarenessContext(previousDPIAwareness);
5412+
}
5413+
}
5414+
}
53855415
}

0 commit comments

Comments
 (0)