From 648876b6b009937f39216a39b10610c50074b2f2 Mon Sep 17 00:00:00 2001 From: Yuhang Zhao <2546789017@qq.com> Date: Sun, 20 Nov 2022 12:56:36 +0800 Subject: [PATCH] win: add a little delay to some operations Signed-off-by: Yuhang Zhao <2546789017@qq.com> --- src/core/framelesshelper_win.cpp | 23 ++++++++++++++--------- src/core/framelessmanager.cpp | 21 +++++++++++++-------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/core/framelesshelper_win.cpp b/src/core/framelesshelper_win.cpp index fd40469..9815266 100644 --- a/src/core/framelesshelper_win.cpp +++ b/src/core/framelesshelper_win.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "framelessmanager.h" #include "framelessmanager_p.h" @@ -639,7 +640,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me const WPARAM wParam = msg->wParam; const LPARAM lParam = msg->lParam; switch (uMsg) { -#if (QT_VERSION < QT_VERSION_CHECK(5, 9, 0)) +#if (QT_VERSION < QT_VERSION_CHECK(5, 9, 0)) // Qt has done this for us since 5.9.0 case WM_NCCREATE: { // Enable automatic DPI scaling for the non-client area of the window, // such as the caption bar, the scrollbars, and the menu bar. We need @@ -1112,7 +1113,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me return true; } } -#if (QT_VERSION < QT_VERSION_CHECK(6, 2, 2)) +#if (QT_VERSION < QT_VERSION_CHECK(6, 2, 2)) // I contributed this to Qt since 6.2.2 case WM_WINDOWPOSCHANGING: { // Tell Windows to discard the entire contents of the client area, as re-using // parts of the client area would lead to jitter during resize. @@ -1127,13 +1128,17 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me << hwnd2str(hWnd) << ": QDpi(" << dpiX << ", " << dpiY << ")."; // Sync the internal window frame margins with the latest DPI. Utils::updateInternalWindowFrameMargins(data.params.getWindowHandle(), true); - // For some unknown reason, Qt sometimes won't re-paint the window contents after - // the DPI changes, and in my experiments the controls should be moved to our - // desired geometry already, the only issue is we don't get the updated appearance - // of our window. And we can workaround this issue by simply triggering a resize - // event manually. There's no need to increase/decrease the window size and then - // change it back, just give Qt our current window size is sufficient enough. - data.params.setWindowSize(data.params.getWindowSize()); + // Here we need a little delay because event filters are processed before + // Qt's own window message handlers. + QTimer::singleShot(50, [data](){ // Copy "data" intentionally, otherwise it'll go out of scope when Qt finally use it. + // For some unknown reason, Qt sometimes won't re-paint the window contents after + // the DPI changes, and in my experiments the controls should be moved to our + // desired geometry already, the only issue is we don't get the updated appearance + // of our window. And we can workaround this issue by simply triggering a resize + // event manually. There's no need to increase/decrease the window size and then + // change it back, just give Qt our current window size is sufficient enough. + data.params.setWindowSize(data.params.getWindowSize()); + }); } break; case WM_DWMCOMPOSITIONCHANGED: { // Re-apply the custom window frame if recovered from the basic theme. diff --git a/src/core/framelessmanager.cpp b/src/core/framelessmanager.cpp index 03f695a..dc16b39 100644 --- a/src/core/framelessmanager.cpp +++ b/src/core/framelessmanager.cpp @@ -25,6 +25,7 @@ #include "framelessmanager_p.h" #include #include +#include #include #include #include @@ -217,14 +218,18 @@ void FramelessManagerPrivate::addWindow(const SystemParameters ¶ms) g_helper()->data[windowId].screenChangeConnection = connect(window, &QWindow::screenChanged, window, [windowId, window](QScreen *screen){ Q_UNUSED(screen); - // Force a WM_NCCALCSIZE event to inform Windows about our custom window frame, - // this is only necessary when the window is being moved cross monitors. - Utils::triggerFrameChange(windowId); - // For some reason the window is not repainted correctly when moving cross monitors, - // we workaround this issue by force a re-paint and re-layout of the window by triggering - // a resize event manually. Although the actual size does not change, the issue we - // observed disappeared indeed, amazingly. - window->resize(window->size()); + // Add a little delay here, make sure it happens after Qt has processed the window + // messages. + QTimer::singleShot(50, window, [windowId, window](){ + // Force a WM_NCCALCSIZE event to inform Windows about our custom window frame, + // this is only necessary when the window is being moved cross monitors. + Utils::triggerFrameChange(windowId); + // For some reason the window is not repainted correctly when moving cross monitors, + // we workaround this issue by force a re-paint and re-layout of the window by triggering + // a resize event manually. Although the actual size does not change, the issue we + // observed disappeared indeed, amazingly. + window->resize(window->size()); + }); }); g_helper()->mutex.unlock(); }