From 1d08c8b1144a62887a2b73903eef4129dc9be207 Mon Sep 17 00:00:00 2001
From: Yuhang Zhao <2546789017@qq.com>
Date: 周二, 04 3月 2025 18:29:06 +0800
Subject: [PATCH] Fix top border & misc tweaks (#167)

---
 src/widgets/widgetwindowagent_win.cpp      |    4 ++--
 src/widgets/widgetwindowagent.cpp          |    2 +-
 src/quick/quickwindowagent_win.cpp         |   13 +++----------
 src/core/shared/windows10borderhandler_p.h |   27 ++++++++++++++++++++++-----
 src/core/contexts/win32windowcontext.cpp   |   10 +++-------
 5 files changed, 31 insertions(+), 25 deletions(-)

diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp
index 00ff1b4..f8a4f67 100644
--- a/src/core/contexts/win32windowcontext.cpp
+++ b/src/core/contexts/win32windowcontext.cpp
@@ -920,13 +920,8 @@
 
         const DynamicApis &apis = DynamicApis::instance();
         const auto &extendMargins = [this, &apis, hwnd]() {
-            // For some unknown reason, the window background is totally black when the host object
-            // is a QWidget. And extending the window frame into the client area seems to fix it
-            // magically.
-            // We don't need the following *HACK* for QtQuick windows.
-            if (!m_host->isWidgetType()) {
-                return;
-            }
+            // For some unknown reason, the window background is totally black and extending
+            // the window frame into the client area seems to fix it magically.
             // After many times of trying, we found that the Acrylic/Mica/Mica Alt background
             // only appears on the native Win32 window's background, so naturally we want to
             // extend the window frame into the whole client area to be able to let the special
@@ -955,6 +950,7 @@
 
         const auto &effectBugWorkaround = [this, hwnd]() {
             // We don't need the following *HACK* for QWidget windows.
+            // Completely based on actual experiments, root reason is totally unknown.
             if (m_host->isWidgetType()) {
                 return;
             }
diff --git a/src/core/shared/windows10borderhandler_p.h b/src/core/shared/windows10borderhandler_p.h
index 8099fe0..8f728f4 100644
--- a/src/core/shared/windows10borderhandler_p.h
+++ b/src/core/shared/windows10borderhandler_p.h
@@ -31,10 +31,12 @@
         }
 
         inline void setupNecessaryAttributes() {
-            // 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);
+            if (!isWin11OrGreater()) {
+                // 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);
+            }
 
             // Enable dark mode by default, otherwise the system borders are white
             ctx->setWindowAttribute(QStringLiteral("dark-mode"), true);
@@ -45,7 +47,17 @@
                      (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen));
         }
 
-        inline void drawBorder() {
+        inline void drawBorderEmulated(QPainter *painter, const QRect &rect) {
+            QRegion region(rect);
+            void *args[] = {
+                painter,
+                const_cast<QRect *>(&rect),
+                &region,
+            };
+            ctx->virtual_hook(AbstractWindowContext::DrawWindows10BorderHook_Emulated, args);
+        }
+
+        inline void drawBorderNative() {
             ctx->virtual_hook(AbstractWindowContext::DrawWindows10BorderHook_Native, nullptr);
         }
 
@@ -54,6 +66,11 @@
         }
 
         inline void updateExtraMargins(bool windowActive) {
+            if (isWin11OrGreater()) {
+                return;
+            }
+
+            // ### FIXME: transparent seam
             if (windowActive) {
                 // Restore margins when the window is active
                 static QVariant defaultMargins = QVariant::fromValue(QMargins(0, 1, 0, 0));
diff --git a/src/quick/quickwindowagent_win.cpp b/src/quick/quickwindowagent_win.cpp
index acfdd42..95bb6f8 100644
--- a/src/quick/quickwindowagent_win.cpp
+++ b/src/quick/quickwindowagent_win.cpp
@@ -97,21 +97,14 @@
     BorderItem::~BorderItem() = default;
 
     void BorderItem::updateGeometry() {
-        setHeight(borderThickness());
+        setHeight(borderThickness() / window()->devicePixelRatio());
         setVisible(isNormalWindow());
     }
 
     void BorderItem::paint(QPainter *painter) {
         Q_UNUSED(painter)
         if (shouldEnableEmulatedPainter()) {
-            QRect rect(QPoint(0, 0), size().toSize());
-            QRegion region(rect);
-            void *args[] = {
-                painter,
-                &rect,
-                &region,
-            };
-            ctx->virtual_hook(AbstractWindowContext::DrawWindows10BorderHook_Emulated, args);
+            drawBorderEmulated(painter, QRect({0, 0}, size().toSize()));
         } else {
             needPaint = true;
         }
@@ -170,7 +163,7 @@
     void BorderItem::_q_afterSynchronizing() {
         if (needPaint) {
             needPaint = false;
-            drawBorder();
+            drawBorderNative();
         }
     }
 
diff --git a/src/widgets/widgetwindowagent.cpp b/src/widgets/widgetwindowagent.cpp
index ca5afa4..1a86d71 100644
--- a/src/widgets/widgetwindowagent.cpp
+++ b/src/widgets/widgetwindowagent.cpp
@@ -61,7 +61,7 @@
         w->setAttribute(Qt::WA_DontCreateNativeAncestors);
         // Make sure the native window handle is actually created before we apply
         // various hooks.
-        w->setAttribute(Qt::WA_NativeWindow); // ### FIXME: Remove
+        //w->setAttribute(Qt::WA_NativeWindow); // ### FIXME: Check
 
         d->setup(w, new WidgetItemDelegate());
         d->hostWidget = w;
diff --git a/src/widgets/widgetwindowagent_win.cpp b/src/widgets/widgetwindowagent_win.cpp
index 1522cab..f7501e0 100644
--- a/src/widgets/widgetwindowagent_win.cpp
+++ b/src/widgets/widgetwindowagent_win.cpp
@@ -83,7 +83,7 @@
             // Due to the timer or user action, Qt will repaint some regions spontaneously,
             // even if there is no WM_PAINT message, we must wait for it to finish painting
             // and then update the top border area.
-            drawBorder();
+            drawBorderNative();
         }
 
         inline void forwardEventToWindowAndDraw(QWindow *window, QEvent *event) {
@@ -97,7 +97,7 @@
 
             // Upon receiving the WM_PAINT message, Qt will repaint the entire view, and we
             // must wait for it to finish painting before drawing this top border area.
-            drawBorder();
+            drawBorderNative();
         }
 
     protected:

--
Gitblit v1.9.1