From 6b2d31247dc2c2804e571b31a71c8a423c1db9d4 Mon Sep 17 00:00:00 2001 From: Sine Striker <trueful@163.com> Date: 周二, 26 12月 2023 01:44:03 +0800 Subject: [PATCH] Totally fix top border issue on Win10 for QtWidgets --- src/core/contexts/abstractwindowcontext.cpp | 56 ++++--- src/widgets/widgetwindowagent_win.cpp | 59 +++---- src/core/contexts/abstractwindowcontext_p.h | 10 - src/core/shared/qwkwindowsextra_p.h | 49 +++++++ src/quick/quickwindowagent_win.cpp | 41 ++++- src/quick/quickwindowagent_p.h | 3 src/widgets/widgetwindowagent_p.h | 1 README.md | 5 src/core/contexts/win32windowcontext.cpp | 158 ++++++---------------- src/core/contexts/win32windowcontext_p.h | 11 - src/core/qwindowkit_windows.h | 8 + examples/mainwindow/mainwindow.cpp | 14 -- src/quick/quickwindowagent.cpp | 2 13 files changed, 198 insertions(+), 219 deletions(-) diff --git a/README.md b/README.md index a466f62..3e56977 100644 --- a/README.md +++ b/README.md @@ -235,16 +235,13 @@ ## Documentations + Examples (TODO) ++ Notes (TODO) + [FramelessHelper Related](docs/framelesshelper-related.md) ## TODO + Fix 5.15 window abnormal behavior -+ Fix window 10 top border color in dark background -+ Fix `isFixedSize` code + Support customized system button area on Mac -+ Implement Mac window context hook -+ Support window attribute switching on Windows ## License diff --git a/examples/mainwindow/mainwindow.cpp b/examples/mainwindow/mainwindow.cpp index 6a7435e..983a7a3 100644 --- a/examples/mainwindow/mainwindow.cpp +++ b/examples/mainwindow/mainwindow.cpp @@ -20,10 +20,6 @@ #include <widgetframe/windowbar.h> #include <widgetframe/windowbutton.h> -#ifdef Q_OS_WINDOWS -# include <QWKCore/qwindowkit_windows.h> -#endif - class ClockWidget : public QLabel { public: explicit ClockWidget(QWidget *parent = nullptr) : QLabel(parent) { @@ -118,16 +114,6 @@ // 1. Setup window agent windowAgent = new QWK::WidgetWindowAgent(this); windowAgent->setup(this); - -#ifdef Q_OS_WIN - if (QWK::IsWindows10OrGreater_Real() && !QWK::IsWindows11OrGreater_Real()) { - // windowAgent->setWindowAttribute(QStringLiteral("dark-mode"), true); - - // https://github.com/microsoft/terminal/blob/71a6f26e6ece656084e87de1a528c4a8072eeabd/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp#L940 - // Must call DWM API to extend top frame to client area - windowAgent->setWindowAttribute(QStringLiteral("extra-margins"), true); - } -#endif // 2. Construct your title bar auto menuBar = [this]() { diff --git a/src/core/contexts/abstractwindowcontext.cpp b/src/core/contexts/abstractwindowcontext.cpp index 8672faf..dc0dc38 100644 --- a/src/core/contexts/abstractwindowcontext.cpp +++ b/src/core/contexts/abstractwindowcontext.cpp @@ -71,32 +71,7 @@ } } - bool AbstractWindowContext::setWindowAttribute(const QString &key, const QVariant &attribute) { - auto it = m_windowAttributes.find(key); - if (it == m_windowAttributes.end()) { - if (!attribute.isValid()) { - return true; - } - if (!m_windowHandle || !windowAttributeChanged(key, attribute, {})) { - return false; - } - m_windowAttributes.insert(key, attribute); - return true; - } - if (it.value() == attribute) - return true; - if (!m_windowHandle || !windowAttributeChanged(key, attribute, it.value())) { - return false; - } - - if (attribute.isValid()) { - it.value() = attribute; - } else { - m_windowAttributes.erase(it); - } - return true; - } bool AbstractWindowContext::setHitTestVisible(const QObject *obj, bool visible) { Q_ASSERT(obj); @@ -285,6 +260,37 @@ } } + QVariant AbstractWindowContext::windowAttribute(const QString &key) const { + return m_windowAttributes.value(key); + } + + bool AbstractWindowContext::setWindowAttribute(const QString &key, const QVariant &attribute) { + auto it = m_windowAttributes.find(key); + if (it == m_windowAttributes.end()) { + if (!attribute.isValid()) { + return true; + } + if (!m_windowHandle || !windowAttributeChanged(key, attribute, {})) { + return false; + } + m_windowAttributes.insert(key, attribute); + return true; + } + + if (it.value() == attribute) + return true; + if (!m_windowHandle || !windowAttributeChanged(key, attribute, it.value())) { + return false; + } + + if (attribute.isValid()) { + it.value() = attribute; + } else { + m_windowAttributes.erase(it); + } + return true; + } + bool AbstractWindowContext::windowAttributeChanged(const QString &key, const QVariant &attribute, const QVariant &oldAttribute) { diff --git a/src/core/contexts/abstractwindowcontext_p.h b/src/core/contexts/abstractwindowcontext_p.h index ec4937a..04651ad 100644 --- a/src/core/contexts/abstractwindowcontext_p.h +++ b/src/core/contexts/abstractwindowcontext_p.h @@ -40,9 +40,6 @@ inline QWindow *window() const; inline WindowItemDelegate *delegate() const; - inline QVariant windowAttribute(const QString &key) const; - bool setWindowAttribute(const QString &key, const QVariant &attribute); - inline bool isHitTestVisible(const QObject *obj) const; bool setHitTestVisible(const QObject *obj, bool visible); @@ -75,6 +72,9 @@ void showSystemMenu(const QPoint &pos); void notifyWinIdChange(); + + virtual QVariant windowAttribute(const QString &key) const; + virtual bool setWindowAttribute(const QString &key, const QVariant &attribute); protected: virtual void winIdChanged() = 0; @@ -110,10 +110,6 @@ inline WindowItemDelegate *AbstractWindowContext::delegate() const { return m_delegate.get(); - } - - inline QVariant AbstractWindowContext::windowAttribute(const QString &key) const { - return m_windowAttributes.value(key); } inline bool AbstractWindowContext::isHitTestVisible(const QObject *obj) const { diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp index 6dec43f..bf25bdb 100644 --- a/src/core/contexts/win32windowcontext.cpp +++ b/src/core/contexts/win32windowcontext.cpp @@ -27,10 +27,6 @@ #include "qwkglobal_p.h" #include "qwkwindowsextra_p.h" -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) -Q_DECLARE_METATYPE(QMargins) -#endif - namespace QWK { // The thickness of an auto-hide taskbar in pixels. @@ -69,55 +65,6 @@ ::SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_FRAMECHANGED); - } - - static inline quint32 getDpiForWindow(HWND hwnd) { - const DynamicApis &apis = DynamicApis::instance(); - if (apis.pGetDpiForWindow) { // Win10 - return apis.pGetDpiForWindow(hwnd); - } else if (apis.pGetDpiForMonitor) { // Win8.1 - HMONITOR monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); - UINT dpiX{0}; - UINT dpiY{0}; - apis.pGetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY); - return dpiX; - } else { // Win2K - HDC hdc = ::GetDC(nullptr); - const int dpiX = ::GetDeviceCaps(hdc, LOGPIXELSX); - // const int dpiY = ::GetDeviceCaps(hdc, LOGPIXELSY); - ::ReleaseDC(nullptr, hdc); - return quint32(dpiX); - } - } - - static inline quint32 getSystemMetricsForDpi(int index, quint32 dpi) { - const DynamicApis &apis = DynamicApis::instance(); - if (apis.pGetSystemMetricsForDpi) { - return ::GetSystemMetricsForDpi(index, dpi); - } - return ::GetSystemMetrics(index); - } - - static inline quint32 getWindowFrameBorderThickness(HWND hwnd) { - const DynamicApis &apis = DynamicApis::instance(); - if (UINT result = 0; SUCCEEDED(apis.pDwmGetWindowAttribute( - hwnd, _DWMWA_VISIBLE_FRAME_BORDER_THICKNESS, &result, sizeof(result)))) { - return result; - } - return getSystemMetricsForDpi(SM_CXBORDER, getDpiForWindow(hwnd)); - } - - static inline quint32 getResizeBorderThickness(HWND hwnd) { - const quint32 dpi = getDpiForWindow(hwnd); - return getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + - getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi); - } - - static inline quint32 getTitleBarHeight(HWND hwnd) { - const quint32 dpi = getDpiForWindow(hwnd); - return getSystemMetricsForDpi(SM_CYCAPTION, dpi) + - getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + - getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi); } static void setInternalWindowFrameMargins(QWindow *window, const QMargins &margins) { @@ -699,8 +646,8 @@ QPoint{m_windowHandle->width(), 0} }); painter.restore(); - return; #endif + return; } case DrawWindows10BorderHook2: { @@ -729,49 +676,35 @@ return; } - // case AbstractWindowContext::DrawWindows10BackgroundHook: { - // #if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER) - // if (!m_windowHandle) - // return; - // - // auto hWnd = reinterpret_cast<HWND>(windowId); - // HDC hdc = ::GetDC(hWnd); - // RECT windowRect{}; - // ::GetClientRect(hWnd, &windowRect); - // RECT rcRest = { - // 0, - // int(getWindowFrameBorderThickness(hWnd)), - // RECT_WIDTH(windowRect), - // RECT_HEIGHT(windowRect), - // }; - // HBRUSH blueBrush = ::CreateSolidBrush(RGB(0, 0, 255)); - // - // // To hide the original title bar, we have to paint on top of it - // with - // // the alpha component set to 255. This is a hack to do it with - // GDI. - // // See NonClientIslandWindow::_UpdateFrameMargins for more - // information. HDC opaqueDc; BP_PAINTPARAMS params = - // {sizeof(params), BPPF_NOCLIP | BPPF_ERASE}; auto buf = - // BeginBufferedPaint(hdc, &rcRest, BPBF_TOPDOWNDIB, ¶ms, - // &opaqueDc); if (!buf || !opaqueDc) { - // return; - // } - // - // ::FillRect(opaqueDc, &rcRest, blueBrush); - // ::BufferedPaintSetAlpha(buf, nullptr, 255); - // ::EndBufferedPaint(buf, TRUE); - // - // ::DeleteObject(blueBrush); - // ::ReleaseDC(hWnd, hdc); - // #endif - // return; - // } - default: break; } AbstractWindowContext::virtual_hook(id, data); + } + + QVariant Win32WindowContext::windowAttribute(const QString &key) const { + if (key == QStringLiteral("title-bar-rect")) { + if (!m_windowHandle) + return {}; + + auto hwnd = reinterpret_cast<HWND>(windowId); + RECT frame{}; + ::AdjustWindowRectExForDpi(&frame, ::GetWindowLongPtrW(hwnd, GWL_STYLE), FALSE, 0, + getDpiForWindow(hwnd)); + return QVariant::fromValue(rect2qrect(frame)); + } + + if (key == QStringLiteral("win10-border-needed")) { + return isSystemBorderEnabled() && !isWin11OrGreater(); + } + + if (key == QStringLiteral("border-thickness")) { + return m_windowHandle + ? int(getWindowFrameBorderThickness(reinterpret_cast<HWND>(windowId))) + : 0; + } + + return AbstractWindowContext::windowAttribute(key); } void Win32WindowContext::winIdChanged() { @@ -790,7 +723,8 @@ auto hWnd = reinterpret_cast<HWND>(winId); if (!isSystemBorderEnabled()) { - setWindowAttribute("extra-margins", true); + setWindowAttribute(QStringLiteral("extra-margins"), + QVariant::fromValue(QMargins(1, 1, 1, 1))); } { @@ -865,17 +799,20 @@ bool Win32WindowContext::windowAttributeChanged(const QString &key, const QVariant &attribute, const QVariant &oldAttribute) { + Q_UNUSED(oldAttribute) + const auto hwnd = reinterpret_cast<HWND>(m_windowHandle->winId()); const DynamicApis &apis = DynamicApis::instance(); - static constexpr const MARGINS defaultEmptyMargins = {0, 0, 0, 0}; - static constexpr const MARGINS defaultExtraMargins = {1, 1, 1, 1}; static constexpr const MARGINS extendedMargins = {-1, -1, -1, -1}; + const auto &restoreMargins = [this, &apis, hwnd]() { + auto margins = qmargins2margins( + m_windowAttributes.value(QStringLiteral("extra-margins")).value<QMargins>()); + apis.pDwmExtendFrameIntoClientArea(hwnd, &margins); + }; + if (key == QStringLiteral("extra-margins")) { - if (isWin11OrGreater()) - return false; - hasExtraMargins = attribute.toBool(); - DynamicApis::instance().pDwmExtendFrameIntoClientArea( - hwnd, hasExtraMargins ? &defaultExtraMargins : &defaultEmptyMargins); + auto margins = qmargins2margins(attribute.value<QMargins>()); + DynamicApis::instance().pDwmExtendFrameIntoClientArea(hwnd, &margins); return true; } @@ -902,8 +839,6 @@ } // For Win11 or later - static const auto &defaultMargins = - isSystemBorderEnabled() ? defaultExtraMargins : defaultEmptyMargins; if (key == QStringLiteral("mica")) { if (!isWin11OrGreater()) { return false; @@ -933,7 +868,7 @@ const BOOL enable = FALSE; apis.pDwmSetWindowAttribute(hwnd, _DWMWA_MICA_EFFECT, &enable, sizeof(enable)); } - apis.pDwmExtendFrameIntoClientArea(hwnd, &defaultMargins); + restoreMargins(); } return true; } @@ -955,7 +890,7 @@ const _DWM_SYSTEMBACKDROP_TYPE backdropType = _DWMSBT_AUTO; apis.pDwmSetWindowAttribute(hwnd, _DWMWA_SYSTEMBACKDROP_TYPE, &backdropType, sizeof(backdropType)); - apis.pDwmExtendFrameIntoClientArea(hwnd, &defaultMargins); + restoreMargins(); } return true; } @@ -1002,7 +937,7 @@ // wcad.cbData = sizeof(policy); // apis.pSetWindowCompositionAttribute(hwnd, &wcad); - apis.pDwmExtendFrameIntoClientArea(hwnd, &defaultMargins); + restoreMargins(); } return true; } @@ -1045,7 +980,7 @@ bb.dwFlags = DWM_BB_ENABLE; apis.pDwmEnableBlurBehindWindow(hwnd, &bb); } - apis.pDwmExtendFrameIntoClientArea(hwnd, &defaultMargins); + restoreMargins(); } return true; } @@ -2080,15 +2015,6 @@ return true; } return false; - } - - bool Win32WindowContext::needBorderPainter() const { - Q_UNUSED(this) - return isSystemBorderEnabled() && !isWin11OrGreater(); - } - - int Win32WindowContext::borderThickness() const { - return int(getWindowFrameBorderThickness(reinterpret_cast<HWND>(windowId))); } } diff --git a/src/core/contexts/win32windowcontext_p.h b/src/core/contexts/win32windowcontext_p.h index baa0254..6a01e16 100644 --- a/src/core/contexts/win32windowcontext_p.h +++ b/src/core/contexts/win32windowcontext_p.h @@ -17,8 +17,6 @@ class Win32WindowContext : public AbstractWindowContext { Q_OBJECT - Q_PROPERTY(bool needBorderPainter READ needBorderPainter FINAL) - Q_PROPERTY(int borderThickness READ borderThickness FINAL) public: Win32WindowContext(); ~Win32WindowContext() override; @@ -34,6 +32,8 @@ QString key() const override; void virtual_hook(int id, void *data) override; + + QVariant windowAttribute(const QString &key) const override; protected: void winIdChanged() override; @@ -59,11 +59,6 @@ bool nonClientCalcSizeHandler(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *result); - public: - bool needBorderPainter() const; - - int borderThickness() const; - protected: WId windowId = 0; @@ -75,8 +70,6 @@ bool mouseLeaveBlocked = false; bool centered = false; - - bool hasExtraMargins = false; }; } diff --git a/src/core/qwindowkit_windows.h b/src/core/qwindowkit_windows.h index 8a98124..998939f 100644 --- a/src/core/qwindowkit_windows.h +++ b/src/core/qwindowkit_windows.h @@ -95,6 +95,14 @@ return (rovi.dwMajorVersion > 6) || (rovi.dwMajorVersion == 6 && rovi.dwMinorVersion >= 2); } + inline bool IsWindows10_Real() { + return IsWindows10OrGreater_Real() && !IsWindows11OrGreater_Real(); + } + } +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +Q_DECLARE_METATYPE(QMargins) +#endif + #endif // QWINDOWKIT_WINDOWS_H diff --git a/src/core/shared/qwkwindowsextra_p.h b/src/core/shared/qwkwindowsextra_p.h index 15fe4e7..8ada487 100644 --- a/src/core/shared/qwkwindowsextra_p.h +++ b/src/core/shared/qwkwindowsextra_p.h @@ -441,6 +441,55 @@ #endif } + static inline quint32 getDpiForWindow(HWND hwnd) { + const DynamicApis &apis = DynamicApis::instance(); + if (apis.pGetDpiForWindow) { // Win10 + return apis.pGetDpiForWindow(hwnd); + } else if (apis.pGetDpiForMonitor) { // Win8.1 + HMONITOR monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); + UINT dpiX{0}; + UINT dpiY{0}; + apis.pGetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY); + return dpiX; + } else { // Win2K + HDC hdc = ::GetDC(nullptr); + const int dpiX = ::GetDeviceCaps(hdc, LOGPIXELSX); + // const int dpiY = ::GetDeviceCaps(hdc, LOGPIXELSY); + ::ReleaseDC(nullptr, hdc); + return quint32(dpiX); + } + } + + static inline quint32 getSystemMetricsForDpi(int index, quint32 dpi) { + const DynamicApis &apis = DynamicApis::instance(); + if (apis.pGetSystemMetricsForDpi) { + return ::GetSystemMetricsForDpi(index, dpi); + } + return ::GetSystemMetrics(index); + } + + static inline quint32 getWindowFrameBorderThickness(HWND hwnd) { + const DynamicApis &apis = DynamicApis::instance(); + if (UINT result = 0; SUCCEEDED(apis.pDwmGetWindowAttribute( + hwnd, _DWMWA_VISIBLE_FRAME_BORDER_THICKNESS, &result, sizeof(result)))) { + return result; + } + return getSystemMetricsForDpi(SM_CXBORDER, getDpiForWindow(hwnd)); + } + + static inline quint32 getResizeBorderThickness(HWND hwnd) { + const quint32 dpi = getDpiForWindow(hwnd); + return getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + + getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi); + } + + static inline quint32 getTitleBarHeight(HWND hwnd) { + const quint32 dpi = getDpiForWindow(hwnd); + return getSystemMetricsForDpi(SM_CYCAPTION, dpi) + + getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + + getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi); + } + } #endif // QWKWINDOWSEXTRA_P_H diff --git a/src/quick/quickwindowagent.cpp b/src/quick/quickwindowagent.cpp index 4e07a3d..100514d 100644 --- a/src/quick/quickwindowagent.cpp +++ b/src/quick/quickwindowagent.cpp @@ -35,7 +35,7 @@ d->setup(window, new QuickItemDelegate()); d->hostWindow = window; -#ifdef Q_OS_WINDOWS +#if defined(Q_OS_WINDOWS) && QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER) d->setupWindows10BorderWorkaround(); #endif return true; diff --git a/src/quick/quickwindowagent_p.h b/src/quick/quickwindowagent_p.h index 15d8b58..8919bdb 100644 --- a/src/quick/quickwindowagent_p.h +++ b/src/quick/quickwindowagent_p.h @@ -10,6 +10,7 @@ // version without notice, or may even be removed. // +#include <QWKCore/qwkconfig.h> #include <QWKCore/private/windowagentbase_p.h> #include <QWKQuick/quickwindowagent.h> @@ -26,7 +27,7 @@ // Host QQuickWindow *hostWindow{}; -#ifdef Q_OS_WINDOWS +#if defined(Q_OS_WINDOWS) && QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER) void setupWindows10BorderWorkaround(); #endif }; diff --git a/src/quick/quickwindowagent_win.cpp b/src/quick/quickwindowagent_win.cpp index 8b2ea86..a1966fd 100644 --- a/src/quick/quickwindowagent_win.cpp +++ b/src/quick/quickwindowagent_win.cpp @@ -4,18 +4,20 @@ #include <QtQuick/private/qquickitem_p.h> #include <QWKCore/qwindowkit_windows.h> -#include <QWKCore/qwkconfig.h> -#include <QWKCore/private/nativeeventfilter_p.h> namespace QWK { #if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER) - class BorderItem : public QQuickPaintedItem, public NativeEventFilter { + class BorderItem : public QQuickPaintedItem, + public NativeEventFilter, + public SharedEventFilter { public: explicit BorderItem(QQuickItem *parent, AbstractWindowContext *context); ~BorderItem() override; - void updateGeometry(); + inline bool isNormalWindow() const; + + inline void updateGeometry(); public: void paint(QPainter *painter) override; @@ -24,6 +26,8 @@ protected: bool nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result) override; + + bool sharedEventFilter(QObject *obj, QEvent *event) override; AbstractWindowContext *context; @@ -47,6 +51,8 @@ setZ(9999); // Make sure our fake border always above everything in the window. context->installNativeEventFilter(this); + context->installSharedEventFilter(this); + connect(window(), &QQuickWindow::activeChanged, this, &BorderItem::_q_windowActivityChanged); updateGeometry(); @@ -54,8 +60,14 @@ BorderItem::~BorderItem() = default; + bool BorderItem::isNormalWindow() const { + return !(context->window()->windowState() & + (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)); + } + void BorderItem::updateGeometry() { - setHeight(context->property("borderThickness").toInt()); + setHeight(context->windowAttribute(QStringLiteral("border-thickness")).toInt()); + setVisible(isNormalWindow()); } void BorderItem::paint(QPainter *painter) { @@ -109,19 +121,30 @@ return false; } + bool BorderItem::sharedEventFilter(QObject *obj, QEvent *event) { + Q_UNUSED(obj) + switch (event->type()) { + case QEvent::WindowStateChange: { + updateGeometry(); + break; + } + default: + break; + } + return false; + } + void BorderItem::_q_windowActivityChanged() { update(); } -#endif void QuickWindowAgentPrivate::setupWindows10BorderWorkaround() { -#if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER) // Install painting hook auto ctx = context.get(); - if (ctx->property("needBorderPainter").toBool()) { + if (ctx->windowAttribute(QStringLiteral("win10-border-needed")).toBool()) { std::ignore = new BorderItem(hostWindow->contentItem(), ctx); } -#endif } +#endif } diff --git a/src/widgets/widgetwindowagent_p.h b/src/widgets/widgetwindowagent_p.h index c5b01be..64702b1 100644 --- a/src/widgets/widgetwindowagent_p.h +++ b/src/widgets/widgetwindowagent_p.h @@ -34,6 +34,7 @@ #if defined(Q_OS_WINDOWS) && QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER) void setupWindows10BorderWorkaround(); + std::unique_ptr<QObject> borderHandler; #endif }; diff --git a/src/widgets/widgetwindowagent_win.cpp b/src/widgets/widgetwindowagent_win.cpp index 9e49d38..3eb6beb 100644 --- a/src/widgets/widgetwindowagent_win.cpp +++ b/src/widgets/widgetwindowagent_win.cpp @@ -5,19 +5,23 @@ #include <QtGui/QPainter> #include <QWKCore/qwindowkit_windows.h> -#include <QWKCore/private/nativeeventfilter_p.h> namespace QWK { #if QWINDOWKIT_CONFIG(ENABLE_WINDOWS_SYSTEM_BORDER) - class WidgetBorderHandler; - class WidgetBorderHandler : public QObject, public NativeEventFilter, public SharedEventFilter { public: - explicit WidgetBorderHandler(QWidget *widget, AbstractWindowContext *ctx) - : QObject(ctx), widget(widget), ctx(ctx) { + explicit WidgetBorderHandler(QWidget *widget, AbstractWindowContext *ctx, + QObject *parent = nullptr) + : QObject(parent), widget(widget), ctx(ctx) { widget->installEventFilter(this); + + // https://github.com/microsoft/terminal/blob/71a6f26e6ece656084e87de1a528c4a8072eeabd/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp#L940 + // Must extend top frame to client area + static QVariant defaultMargins = QVariant::fromValue(QMargins(0, 1, 0, 0)); + ctx->setWindowAttribute(QStringLiteral("extra-margins"), defaultMargins); + ctx->setWindowAttribute(QStringLiteral("dark-mode"), true); ctx->installNativeEventFilter(this); ctx->installSharedEventFilter(this); @@ -30,14 +34,10 @@ (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)); } - void updateGeometry() { + inline void updateGeometry() { if (isNormalWindow()) { - widget->setContentsMargins({ - 0, - ctx->property("borderThickness").toInt(), - 0, - 0, - }); + widget->setContentsMargins( + {0, ctx->windowAttribute(QStringLiteral("border-thickness")).toInt(), 0, 0}); } else { widget->setContentsMargins({}); } @@ -54,31 +54,24 @@ break; } - case WM_THEMECHANGED: - case WM_SYSCOLORCHANGE: - case WM_DWMCOLORIZATIONCOLORCHANGED: { - widget->update(); - break; - } - - case WM_SETTINGCHANGE: { - if (!msg->wParam && msg->lParam && - std::wcscmp(reinterpret_cast<LPCWSTR>(msg->lParam), L"ImmersiveColorSet") == - 0) { - widget->update(); - } - break; - } -# if 0 case WM_ACTIVATE: { if (LOWORD(msg->wParam) == WA_INACTIVE) { - // 绐楀彛澶卞幓婵�娲荤姸鎬� + // https://github.com/microsoft/terminal/blob/71a6f26e6ece656084e87de1a528c4a8072eeabd/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp#L904 + // When the window is inactive, there is a transparency bug in the top + // border and we needs to extend the non-client area to the whole title + // bar. + QRect frame = + ctx->windowAttribute(QStringLiteral("title-bar-rect")).toRect(); + QMargins margins{0, -frame.top(), 0, 0}; + ctx->setWindowAttribute(QStringLiteral("extra-margins"), + QVariant::fromValue(margins)); } else { - // 绐楀彛琚縺娲� + // Restore margins when the window is active + static QVariant defaultMargins = QVariant::fromValue(QMargins(0, 1, 0, 0)); + ctx->setWindowAttribute(QStringLiteral("extra-margins"), defaultMargins); } break; } -# endif default: break; @@ -162,8 +155,8 @@ void WidgetWindowAgentPrivate::setupWindows10BorderWorkaround() { // Install painting hook auto ctx = context.get(); - if (ctx->property("needBorderPainter").toBool()) { - std::ignore = new WidgetBorderHandler(hostWidget, ctx); + if (ctx->windowAttribute(QStringLiteral("win10-border-needed")).toBool()) { + borderHandler = std::make_unique<WidgetBorderHandler>(hostWidget, ctx); } } #endif -- Gitblit v1.9.1