From 1f1de5deb67ccab73749c4af6ed433f9fe4e8626 Mon Sep 17 00:00:00 2001 From: Altair Wei Date: Thu, 7 Oct 2021 11:27:56 +0800 Subject: [PATCH] fix window maximization bugs on Windows --- framelesshelper.cpp | 63 ++++++++++----------------------------- framelesshelper.h | 5 ---- framelesshelper_win32.cpp | 2 +- 3 files changed, 17 insertions(+), 53 deletions(-) diff --git a/framelesshelper.cpp b/framelesshelper.cpp index e042f1a..07355d5 100644 --- a/framelesshelper.cpp +++ b/framelesshelper.cpp @@ -97,7 +97,7 @@ void FramelessHelper::install() #endif #ifdef Q_OS_WIN - updateQtFrameMargins(true); + Utilities::updateQtFrameMargins(m_window, true); const WId winId = m_window->winId(); Utilities::updateFrameMargins(winId, !true); Utilities::triggerFrameChange(winId); @@ -123,7 +123,7 @@ void FramelessHelper::uninstall() #endif #ifdef Q_OS_WIN - updateQtFrameMargins(false); + Utilities::updateQtFrameMargins(m_window, false); const WId winId = m_window->winId(); Utilities::updateFrameMargins(winId, !false); Utilities::triggerFrameChange(winId); @@ -631,34 +631,6 @@ static inline bool shouldHaveWindowFrame() return false; } -Q_DECLARE_METATYPE(QMargins) -void FramelessHelper::updateQtFrameMargins(const bool enable) -{ - const bool useCustomFrameMargin = (enable && (m_window->windowState() != Qt::WindowMaximized) - && (m_window->windowState() != Qt::WindowFullScreen)); - const int resizeBorderThickness = useCustomFrameMargin ? this->resizeBorderThickness() : 0; - const int titleBarHeight = enable ? this->titleBarHeight() : 0; - const QMargins margins = {-resizeBorderThickness, -titleBarHeight, -resizeBorderThickness, -resizeBorderThickness}; // left, top, right, bottom - const QVariant marginsVar = QVariant::fromValue(margins); - m_window->setProperty("_q_windowsCustomMargins", marginsVar); -#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) - QPlatformWindow *platformWindow = m_window->handle(); - if (platformWindow) { - QGuiApplication::platformNativeInterface()->setWindowProperty(platformWindow, QStringLiteral("WindowsCustomMargins"), marginsVar); - } else { - qWarning() << "Failed to retrieve the platform window."; - } -#else - auto *platformWindow = dynamic_cast( - m_window->handle()); - if (platformWindow) { - platformWindow->setCustomMargins(margins); - } else { - qWarning() << "Failed to retrieve the platform window."; - } -#endif -} - /*! This function works like a eventFilter, return \c true means the event has been handled. */ @@ -688,8 +660,8 @@ bool FramelessHelper::handleNativeEvent(QWindow *window, const QByteArray &event if (!window) return false; - // 所有从 Qt 获得的值必须乘以放大倍速,所有传给 Qt 的值必须除以放大倍数。 - // TODO: 全屏情况下 hitTestVisible 区域的计算有问题。很可能是全屏时,边框剪切造成的按钮位置偏移。 + // All values obtained from Qt must be multiplied by the scaleFactor, + // and all values passed to Qt must be divided by the scaleFactor. qreal scaleFactor = m_window->screen()->devicePixelRatio(); switch (msg->message) { @@ -775,10 +747,14 @@ bool FramelessHelper::handleNativeEvent(QWindow *window, const QByteArray &event const auto clientRect = &(reinterpret_cast(msg->lParam)->rgrc[0]); - resizeWindow(QSize( - qRound((clientRect->right - clientRect->left) / scaleFactor), - qRound((clientRect->bottom - clientRect->top) / scaleFactor) - )); + // In order to determine the area of the title bar, we need to record + // the geometric area of the new window size. + resizeWindow( + QSize( + qRound((clientRect->right - clientRect->left) / scaleFactor), + qRound((clientRect->bottom - clientRect->top) / scaleFactor) + ) + ); if (shouldHaveWindowFrame()) { // Store the original top before the default window proc @@ -805,8 +781,10 @@ bool FramelessHelper::handleNativeEvent(QWindow *window, const QByteArray &event // then the window is clipped to the monitor so that the resize handle // do not appear because you don't need them (because you can't resize // a window when it's maximized unless you restore it). - const int resizeBorderThickness = qRound( - static_cast(this->resizeBorderThickness()) * scaleFactor); + + // Get system default resize border thickness. + const int resizeBorderThickness = Utilities::getSystemMetric( + window, SystemMetric::ResizeBorderThickness, true, true); clientRect->top += resizeBorderThickness; if (!shouldHaveWindowFrame()) { clientRect->bottom -= resizeBorderThickness; @@ -1200,15 +1178,6 @@ bool FramelessHelper::handleNativeEvent(QWindow *window, const QByteArray &event *result = ret; return true; } - case WM_SIZE: { - const bool normal = (msg->wParam == SIZE_RESTORED); - const bool max = (msg->wParam == SIZE_MAXIMIZED); - const bool full = (window->windowState() == Qt::WindowFullScreen); - if (normal || max || full) { - Utilities::updateFrameMargins(reinterpret_cast(msg->hwnd), (max || full)); - updateQtFrameMargins(true); - } - } break; default: break; } diff --git a/framelesshelper.h b/framelesshelper.h index 8492f2c..0362814 100644 --- a/framelesshelper.h +++ b/framelesshelper.h @@ -97,11 +97,6 @@ public: #endif #endif // Q_OS_WIN -private: -#ifdef Q_OS_WIN - void updateQtFrameMargins(const bool enable); -#endif // Q_OS_WIN - protected: bool eventFilter(QObject *object, QEvent *event) override; void handleResizeHandlerDblClicked(); diff --git a/framelesshelper_win32.cpp b/framelesshelper_win32.cpp index 3920718..74261b8 100644 --- a/framelesshelper_win32.cpp +++ b/framelesshelper_win32.cpp @@ -281,7 +281,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me // then the window is clipped to the monitor so that the resize handle // do not appear because you don't need them (because you can't resize // a window when it's maximized unless you restore it). - const int resizeBorderThickness = Utilities::getSystemMetric(window, SystemMetric::ResizeBorderThickness, true); + const int resizeBorderThickness = Utilities::getSystemMetric(window, SystemMetric::ResizeBorderThickness, false, true); clientRect->top += resizeBorderThickness; if (!shouldHaveWindowFrame()) { clientRect->bottom -= resizeBorderThickness;