From 9b1599d82e86d2d0463b60fe6fa61f94be50f983 Mon Sep 17 00:00:00 2001
From: Yuhang Zhao <zhaoyuhang@rankyee.com>
Date: 周二, 05 12月 2023 14:48:52 +0800
Subject: [PATCH] port some more code (for os < win10)

---
 src/core/contexts/win32windowcontext.cpp |   94 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 92 insertions(+), 2 deletions(-)

diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp
index d3b34ec..49a6d69 100644
--- a/src/core/contexts/win32windowcontext.cpp
+++ b/src/core/contexts/win32windowcontext.cpp
@@ -28,6 +28,7 @@
 
     struct DynamicApis {
         decltype(&::DwmFlush) pDwmFlush = nullptr;
+        decltype(&::DwmIsCompositionEnabled) pDwmIsCompositionEnabled = nullptr;
         decltype(&::GetDpiForWindow) pGetDpiForWindow = nullptr;
         decltype(&::GetSystemMetricsForDpi) pGetSystemMetricsForDpi = nullptr;
         decltype(&::GetDpiForMonitor) pGetDpiForMonitor = nullptr;
@@ -45,6 +46,7 @@
 
             QSystemLibrary dwmapi(QStringLiteral("dwmapi.dll"));
             pDwmFlush = reinterpret_cast<decltype(pDwmFlush)>(dwmapi.resolve("DwmFlush"));
+            pDwmIsCompositionEnabled = reinterpret_cast<decltype(pDwmIsCompositionEnabled)>(dwmapi.resolve("DwmIsCompositionEnabled"));
         }
 
         ~DynamicApis() = default;
@@ -138,6 +140,12 @@
         return hwnd2str(reinterpret_cast<WId>(hwnd));
     }
 
+    static inline bool isWin8OrGreater() {
+        static const bool result =
+            QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8;
+        return result;
+    }
+
     static inline bool isWin8Point1OrGreater() {
         static const bool result =
             QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8_1;
@@ -148,6 +156,26 @@
         static const bool result =
             QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10;
         return result;
+    }
+
+    static inline bool isDwmCompositionEnabled() {
+        if (isWin8OrGreater()) {
+            return true;
+        }
+        const DynamicApis &apis = DynamicApis::instance();
+        if (!apis.pDwmIsCompositionEnabled) {
+            return false;
+        }
+        BOOL enabled = FALSE;
+        return SUCCEEDED(apis.pDwmIsCompositionEnabled(&enabled)) && enabled;
+    }
+
+    static inline void triggerFrameChange(HWND hwnd) {
+        Q_ASSERT(hwnd);
+        if (!hwnd) {
+            return;
+        }
+        ::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) {
@@ -266,7 +294,7 @@
             case HTBORDER:
                 return Win32WindowContext::FixedBorder;
             default:
-                break;
+                break; // unreachable
         }
         return Win32WindowContext::Outside;
     }
@@ -1087,7 +1115,7 @@
                 // window can behave just like a normal Win32 window even if we now
                 // doesn't have a title bar at all. Most importantly, the flicker and
                 // jitter during window resizing is totally gone now. The disadvantage
-                // is we have to draw a top frame border ourself. Previously I thought
+                // is we have to draw a top frame border ourselves. Previously I thought
                 // we have to do the black magic in WM_PAINT just like what Windows
                 // Terminal does, however, later I found that if we choose a proper
                 // color, our homemade top border can almost have exactly the same
@@ -1165,6 +1193,8 @@
                                 break;
                             case CoreWindowAgent::Unknown:
                                 break;
+                            default:
+                                break; // unreachable
                         }
                     }
                     if (*result == HTNOWHERE) {
@@ -1291,6 +1321,66 @@
             default:
                 break;
         }
+        if (!isWin10OrGreater()) {
+            switch (message) {
+                case WM_NCUAHDRAWCAPTION:
+                case WM_NCUAHDRAWFRAME: {
+                    // These undocumented messages are sent to draw themed window
+                    // borders. Block them to prevent drawing borders over the client
+                    // area.
+                    *result = FALSE;
+                    return true;
+                }
+                case WM_NCPAINT: {
+                    // 杈规闃村奖澶勪簬闈炲鎴峰尯鐨勮寖鍥达紝鍥犳濡傛灉鐩存帴闃绘闈炲鎴峰尯鐨勭粯鍒讹紝浼氬鑷磋竟妗嗛槾褰变涪澶�
+
+                    if (!isDwmCompositionEnabled()) {
+                        // Only block WM_NCPAINT when DWM composition is disabled. If
+                        // it's blocked when DWM composition is enabled, the frame
+                        // shadow won't be drawn.
+                        *result = FALSE;
+                        return true;
+                    } else {
+                        break;
+                    }
+                }
+                case WM_NCACTIVATE: {
+                    if (isDwmCompositionEnabled()) {
+                        // DefWindowProc won't repaint the window border if lParam (normally a HRGN)
+                        // is -1. See the following link's "lParam" section:
+                        // https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-ncactivate
+                        // Don't use "*result = 0" here, otherwise the window won't respond to the
+                        // window activation state change.
+                        *result = ::DefWindowProcW(hWnd, WM_NCACTIVATE, wParam, -1);
+                    } else {
+                        if (wParam == FALSE) {
+                            *result = TRUE;
+                        } else {
+                            *result = FALSE;
+                        }
+                    }
+                    return true;
+                }
+                case WM_SETICON:
+                case WM_SETTEXT: {
+                    // Disable painting while these messages are handled to prevent them
+                    // from drawing a window caption over the client area.
+                    const auto oldStyle = static_cast<DWORD>(::GetWindowLongPtrW(hWnd, GWL_STYLE));
+                    // Prevent Windows from drawing the default title bar by temporarily
+                    // toggling the WS_VISIBLE style.
+                    const DWORD newStyle = (oldStyle & ~WS_VISIBLE);
+                    ::SetWindowLongPtrW(hWnd, GWL_STYLE, static_cast<LONG_PTR>(newStyle));
+                    triggerFrameChange(hWnd);
+                    const LRESULT originalResult = ::DefWindowProcW(hWnd, message, wParam, lParam);
+                    ::SetWindowLongPtrW(hWnd, GWL_STYLE, static_cast<LONG_PTR>(oldStyle));
+                    triggerFrameChange(hWnd);
+                    *result = originalResult;
+                    return true;
+                }
+                default:
+                    break;
+            }
+        }
         return false;
     }
 

--
Gitblit v1.9.1