win: add a little delay to some operations

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2022-11-20 12:56:36 +08:00
parent 04f254556d
commit 648876b6b0
2 changed files with 27 additions and 17 deletions

View File

@ -27,6 +27,7 @@
#include <QtCore/qmutex.h>
#include <QtCore/qvariant.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qtimer.h>
#include <QtGui/qwindow.h>
#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.

View File

@ -25,6 +25,7 @@
#include "framelessmanager_p.h"
#include <QtCore/qmutex.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qtimer.h>
#include <QtGui/qscreen.h>
#include <QtGui/qwindow.h>
#include <QtGui/qfontdatabase.h>
@ -217,14 +218,18 @@ void FramelessManagerPrivate::addWindow(const SystemParameters &params)
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();
}