From 29901fc2a97eedd3c914f807d1819c9ea7e69973 Mon Sep 17 00:00:00 2001 From: Sine Striker <trueful@163.com> Date: 周一, 25 12月 2023 17:53:34 +0800 Subject: [PATCH] Optimize Windows 10 border handling --- src/core/contexts/win32windowcontext.cpp | 155 +++++++++++++++++++++++++++++++++------------------ 1 files changed, 100 insertions(+), 55 deletions(-) diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp index 9b92b0d..6dec43f 100644 --- a/src/core/contexts/win32windowcontext.cpp +++ b/src/core/contexts/win32windowcontext.cpp @@ -729,27 +729,49 @@ 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); - } - - bool Win32WindowContext::needBorderPainter() const { - Q_UNUSED(this) - return isSystemBorderEnabled() && !isWin11OrGreater(); - } - - int Win32WindowContext::borderThickness() const { - return int(getWindowFrameBorderThickness(reinterpret_cast<HWND>(windowId))); - } - - void Win32WindowContext::resume(const QByteArray &eventType, void *message, - QT_NATIVE_EVENT_RESULT_TYPE *result) { - const auto msg = static_cast<const MSG *>(message); - LRESULT res = - ::CallWindowProcW(g_qtWindowProc, msg->hwnd, msg->message, msg->wParam, msg->lParam); - *result = decltype(*result)(res); } void Win32WindowContext::winIdChanged() { @@ -768,13 +790,7 @@ auto hWnd = reinterpret_cast<HWND>(winId); if (!isSystemBorderEnabled()) { - static constexpr const MARGINS margins = {1, 1, 1, 1}; - DynamicApis::instance().pDwmExtendFrameIntoClientArea(hWnd, &margins); - } else if (isWin10OrGreater() && !isWin11OrGreater()) { - // https://github.com/microsoft/terminal/blob/71a6f26e6ece656084e87de1a528c4a8072eeabd/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp#L940 - // Must call DWM API to extend top frame to client area - static constexpr const MARGINS margins = {0, 0, 1, 0}; - DynamicApis::instance().pDwmExtendFrameIntoClientArea(hWnd, &margins); + setWindowAttribute("extra-margins", true); } { @@ -839,7 +855,7 @@ msg.wParam = wParam; msg.lParam = lParam; QT_NATIVE_EVENT_RESULT_TYPE res = 0; - if (dispatch(QByteArrayLiteral("windows_generic_MSG"), &msg, &res)) { + if (nativeDispatch(QByteArrayLiteral("windows_generic_MSG"), &msg, &res)) { *result = LRESULT(res); return true; } @@ -851,9 +867,43 @@ const QVariant &oldAttribute) { const auto hwnd = reinterpret_cast<HWND>(m_windowHandle->winId()); const DynamicApis &apis = DynamicApis::instance(); - static constexpr const MARGINS extendMargins = {-1, -1, -1, -1}; - static const auto defaultMargins = - isSystemBorderEnabled() ? MARGINS{0, 0, 0, 0} : MARGINS{1, 1, 1, 1}; + 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}; + if (key == QStringLiteral("extra-margins")) { + if (isWin11OrGreater()) + return false; + hasExtraMargins = attribute.toBool(); + DynamicApis::instance().pDwmExtendFrameIntoClientArea( + hwnd, hasExtraMargins ? &defaultExtraMargins : &defaultEmptyMargins); + return true; + } + + if (key == QStringLiteral("dark-mode")) { + if (!isWin101809OrGreater()) { + return false; + } + + BOOL enable = attribute.toBool(); + if (isWin101903OrGreater()) { + apis.pSetPreferredAppMode(enable ? PAM_AUTO : PAM_DEFAULT); + } else { + apis.pAllowDarkModeForApp(enable); + } + for (const auto attr : { + _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, + _DWMWA_USE_IMMERSIVE_DARK_MODE, + }) { + apis.pDwmSetWindowAttribute(hwnd, attr, &enable, sizeof(enable)); + } + + apis.pFlushMenuThemes(); + return true; + } + + // For Win11 or later + static const auto &defaultMargins = + isSystemBorderEnabled() ? defaultExtraMargins : defaultEmptyMargins; if (key == QStringLiteral("mica")) { if (!isWin11OrGreater()) { return false; @@ -861,7 +911,7 @@ if (attribute.toBool()) { // We need to extend the window frame into the whole client area to be able // to see the blurred window background. - apis.pDwmExtendFrameIntoClientArea(hwnd, &extendMargins); + apis.pDwmExtendFrameIntoClientArea(hwnd, &extendedMargins); if (isWin1122H2OrGreater()) { // Use official DWM API to enable Mica, available since Windows 11 22H2 // (10.0.22621). @@ -886,14 +936,16 @@ apis.pDwmExtendFrameIntoClientArea(hwnd, &defaultMargins); } return true; - } else if (key == QStringLiteral("mica-alt")) { + } + + if (key == QStringLiteral("mica-alt")) { if (!isWin1122H2OrGreater()) { return false; } if (attribute.toBool()) { // We need to extend the window frame into the whole client area to be able // to see the blurred window background. - apis.pDwmExtendFrameIntoClientArea(hwnd, &extendMargins); + apis.pDwmExtendFrameIntoClientArea(hwnd, &extendedMargins); // Use official DWM API to enable Mica Alt, available since Windows 11 22H2 // (10.0.22621). const _DWM_SYSTEMBACKDROP_TYPE backdropType = _DWMSBT_TABBEDWINDOW; @@ -906,14 +958,16 @@ apis.pDwmExtendFrameIntoClientArea(hwnd, &defaultMargins); } return true; - } else if (key == QStringLiteral("acrylic-material")) { + } + + if (key == QStringLiteral("acrylic-material")) { if (!isWin11OrGreater()) { return false; } if (attribute.toBool()) { // We need to extend the window frame into the whole client area to be able // to see the blurred window background. - apis.pDwmExtendFrameIntoClientArea(hwnd, &extendMargins); + apis.pDwmExtendFrameIntoClientArea(hwnd, &extendedMargins); const _DWM_SYSTEMBACKDROP_TYPE backdropType = _DWMSBT_TRANSIENTWINDOW; apis.pDwmSetWindowAttribute(hwnd, _DWMWA_SYSTEMBACKDROP_TYPE, &backdropType, @@ -951,13 +1005,15 @@ apis.pDwmExtendFrameIntoClientArea(hwnd, &defaultMargins); } return true; - } else if (key == QStringLiteral("dwm-blur")) { + } + + if (key == QStringLiteral("dwm-blur")) { // TODO: Optimize // Currently not available!!! if (attribute.toBool()) { // We need to extend the window frame into the whole client area to be able // to see the blurred window background. - apis.pDwmExtendFrameIntoClientArea(hwnd, &extendMargins); + apis.pDwmExtendFrameIntoClientArea(hwnd, &extendedMargins); if (isWin8OrGreater()) { ACCENT_POLICY policy{}; policy.dwAccentState = ACCENT_ENABLE_BLURBEHIND; @@ -991,26 +1047,6 @@ } apis.pDwmExtendFrameIntoClientArea(hwnd, &defaultMargins); } - return true; - } else if (key == QStringLiteral("dark-mode")) { - if (!isWin101809OrGreater()) { - return false; - } - - BOOL enable = attribute.toBool(); - if (isWin101903OrGreater()) { - apis.pSetPreferredAppMode(enable ? PAM_AUTO : PAM_DEFAULT); - } else { - apis.pAllowDarkModeForApp(enable); - } - for (const auto attr : { - _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, - _DWMWA_USE_IMMERSIVE_DARK_MODE, - }) { - apis.pDwmSetWindowAttribute(hwnd, attr, &enable, sizeof(enable)); - } - - apis.pFlushMenuThemes(); return true; } return false; @@ -2046,4 +2082,13 @@ return false; } + bool Win32WindowContext::needBorderPainter() const { + Q_UNUSED(this) + return isSystemBorderEnabled() && !isWin11OrGreater(); + } + + int Win32WindowContext::borderThickness() const { + return int(getWindowFrameBorderThickness(reinterpret_cast<HWND>(windowId))); + } + } -- Gitblit v1.9.1