From 5a0e5a9261c251dba54afb8cc0b6b32ae9d95510 Mon Sep 17 00:00:00 2001 From: Zhao Yuhang <2546789017@qq.com> Date: 周二, 12 12月 2023 19:50:34 +0800 Subject: [PATCH] add theme win32 message --- src/core/contexts/win32windowcontext.cpp | 223 +++++++++++++++++++++++++++++++------------------------ 1 files changed, 124 insertions(+), 99 deletions(-) diff --git a/src/core/contexts/win32windowcontext.cpp b/src/core/contexts/win32windowcontext.cpp index 297c39c..372d0c5 100644 --- a/src/core/contexts/win32windowcontext.cpp +++ b/src/core/contexts/win32windowcontext.cpp @@ -29,6 +29,8 @@ #include "nativeeventfilter.h" #include "qwkglobal_p.h" +#include "win10borderhandler_p.h" + #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) Q_DECLARE_METATYPE(QMargins) #endif @@ -357,44 +359,37 @@ } } - static inline quint32 getWindowFrameBorderThickness(HWND hwnd) { - UINT result = 0; + static inline quint32 getSystemMetricsForDpi(int index, quint32 dpi) { const DynamicApis &apis = DynamicApis::instance(); - if (SUCCEEDED(apis.pDwmGetWindowAttribute(hwnd, _DWMWA_VISIBLE_FRAME_BORDER_THICKNESS, - &result, sizeof(result)))) { - return result; - } else { - const quint32 dpi = getDpiForWindow(hwnd); - result = quint32(std::round(qreal(1) * qreal(dpi) / qreal(USER_DEFAULT_SCREEN_DPI))); + 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 DynamicApis &apis = DynamicApis::instance(); - if (apis.pGetSystemMetricsForDpi) { - const quint32 dpi = getDpiForWindow(hwnd); - return apis.pGetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + - apis.pGetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi); - } else { - return ::GetSystemMetrics(SM_CXSIZEFRAME) + ::GetSystemMetrics(SM_CXPADDEDBORDER); - } + const quint32 dpi = getDpiForWindow(hwnd); + return getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + + getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi); } static inline quint32 getTitleBarHeight(HWND hwnd) { - const auto captionHeight = [hwnd]() -> int { - const DynamicApis &apis = DynamicApis::instance(); - if (apis.pGetSystemMetricsForDpi) { - const quint32 dpi = getDpiForWindow(hwnd); - return apis.pGetSystemMetricsForDpi(SM_CYCAPTION, dpi); - } else { - return ::GetSystemMetrics(SM_CYCAPTION); - } - }(); - return captionHeight + getResizeBorderThickness(hwnd); + const quint32 dpi = getDpiForWindow(hwnd); + return getSystemMetricsForDpi(SM_CYCAPTION, dpi) + + getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + + getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi); } - static inline void updateInternalWindowFrameMargins(HWND hwnd, QWindow *window) { + static void updateInternalWindowFrameMargins(HWND hwnd, QWindow *window) { const auto margins = [hwnd]() -> QMargins { const auto titleBarHeight = int(getTitleBarHeight(hwnd)); if (isWin10OrGreater()) { @@ -460,7 +455,7 @@ #endif } - static inline void syncPaintEventWithDwm() { + static void syncPaintEventWithDwm() { // No need to sync with DWM if DWM composition is disabled. if (!isDwmCompositionEnabled()) { return; @@ -505,9 +500,9 @@ apis.ptimeEndPeriod(ms_granularity); } - static inline void showSystemMenu2(HWND hWnd, const POINT &pos, const bool selectFirstEntry, - const bool fixedSize) { - const HMENU hMenu = ::GetSystemMenu(hWnd, FALSE); + static void showSystemMenu2(HWND hWnd, const POINT &pos, const bool selectFirstEntry, + const bool fixedSize) { + HMENU hMenu = ::GetSystemMenu(hWnd, FALSE); if (!hMenu) { // The corresponding window doesn't have a system menu, most likely due to the // lack of the "WS_SYSMENU" window style. This situation should not be treated @@ -809,74 +804,13 @@ return; } - case NeedsDrawBordersHook: { - auto &result = *static_cast<bool *>(data); - result = isWin10OrGreater() && !isWin11OrGreater(); - return; - } - - case BorderThicknessHook: { - auto args = static_cast<void **>(data); - const bool requireNative = *static_cast<const bool *>(args[0]); - quint32 &thickness = *static_cast<quint32 *>(args[1]); - const auto hwnd = reinterpret_cast<HWND>(m_windowHandle->winId()); - const auto nativeThickness = getWindowFrameBorderThickness(hwnd); - thickness = requireNative - ? nativeThickness - : QHighDpi::fromNativePixels(nativeThickness, m_windowHandle); - return; - } - - case BorderColorsHook: { - auto arr = *reinterpret_cast<QList<QColor> *>(data); - arr.clear(); - arr.push_back(kWindowsColorSet.activeLight); - arr.push_back(kWindowsColorSet.activeDark); - arr.push_back(kWindowsColorSet.inactiveLight); - arr.push_back(kWindowsColorSet.inactiveDark); - return; - } - - case DrawBordersHook: { - auto args = static_cast<void **>(data); - auto &painter = *static_cast<QPainter *>(args[0]); - const auto &rect = *static_cast<const QRect *>(args[1]); - const auto ®ion = *static_cast<const QRegion *>(args[2]); - const auto hwnd = reinterpret_cast<HWND>(m_windowHandle->winId()); - - QPen pen; - const auto borderThickness = int(QHighDpi::fromNativePixels( - getWindowFrameBorderThickness(hwnd), m_windowHandle)); - pen.setWidth(borderThickness * 2); - const bool active = m_delegate->isWindowActive(m_host); - const bool dark = isDarkThemeActive() && isDarkWindowFrameEnabled(hwnd); - - if (active) { - if (isWindowFrameBorderColorized()) { - pen.setColor(getAccentColor()); - } else { - static QColor frameBorderActiveColorLight(kWindowsColorSet.activeLight); - static QColor frameBorderActiveColorDark(kWindowsColorSet.activeDark); - pen.setColor(dark ? frameBorderActiveColorDark - : frameBorderActiveColorLight); - } - } else { - static QColor frameBorderInactiveColorLight(kWindowsColorSet.inactiveLight); - static QColor frameBorderInactiveColorDark(kWindowsColorSet.inactiveDark); - pen.setColor(dark ? frameBorderInactiveColorDark - : frameBorderInactiveColorLight); - } - painter.save(); - - // ### TODO: do we need to enable or disable it? - painter.setRenderHint(QPainter::Antialiasing); - - painter.setPen(pen); - painter.drawLine(QLine{ - QPoint{0, 0}, - QPoint{rect.width(), 0} - }); - painter.restore(); + case DefaultColorsHook: { + auto &map = *static_cast<QMap<QString, QColor> *>(data); + map.clear(); + map.insert(QStringLiteral("activeLight"), kWindowsColorSet.activeLight); + map.insert(QStringLiteral("activeDark"), kWindowsColorSet.activeDark); + map.insert(QStringLiteral("inactiveLight"), kWindowsColorSet.inactiveLight); + map.insert(QStringLiteral("inactiveDark"), kWindowsColorSet.inactiveDark); return; } @@ -886,6 +820,16 @@ } } AbstractWindowContext::virtual_hook(id, data); + } + + bool Win32WindowContext::needWin10BorderHandler() const { + return isWin10OrGreater() && !isWin11OrGreater(); + } + + void Win32WindowContext::setWin10BorderHandler(Win10BorderHandler *handler) { + win10BorderHandler.reset(handler); + handler->setBorderThickness( + int(getWindowFrameBorderThickness(reinterpret_cast<HWND>(windowId)))); } bool Win32WindowContext::setupHost() { @@ -950,6 +894,10 @@ // Whether to show system menu if (systemMenuHandler(hWnd, message, wParam, lParam, result)) { + return true; + } + + if (themeStuffHandler(hWnd, message, wParam, lParam, result)) { return true; } @@ -1939,4 +1887,81 @@ return false; } + bool Win32WindowContext::themeStuffHandler(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, + LRESULT *resul) + { + switch (message) { + case WM_DPICHANGED: { + const auto dpiX = UINT(LOWORD(wParam)); + const auto dpiY = UINT(HIWORD(wParam)); + break; + } + case WM_THEMECHANGED: + case WM_SYSCOLORCHANGE: { + break; + } + case WM_DWMCOLORIZATIONCOLORCHANGED: { + const QColor color = QColor::fromRgba(wParam); + const auto blendWithOpacity = *reinterpret_cast<LPBOOL>(lParam); + break; + } + case WM_SETTINGCHANGE: { + if (!wParam && lParam && std::wcscmp(reinterpret_cast<LPCWSTR>(lParam), L"ImmersiveColorSet") == 0) { + const QColor color = getAccentColor(); + } + break; + } + case WM_SIZE: { + const bool max = wParam == SIZE_MAXIMIZED; + const bool min = wParam == SIZE_MINIMIZED; + const bool full = isFullScreen(hWnd); + break; + } + case WM_ACTIVATE: { + const auto state = LOWORD(wParam); + const bool active = state == WA_ACTIVE || state == WA_CLICKACTIVE; + break; + } + default: + break; + } + return false; + } + + void Win10BorderHandler::paintBorder(QPainter &painter, const QRect &rect, + const QRegion ®ion) { + Q_UNUSED(rect) + Q_UNUSED(region) + + QPen pen; + pen.setWidth(m_borderThickness * 2); + + const bool dark = isDarkThemeActive() && + isDarkWindowFrameEnabled(reinterpret_cast<HWND>(m_window->winId())); + if (isActive()) { + if (isWindowFrameBorderColorized()) { + pen.setColor(getAccentColor()); + } else { + static QColor frameBorderActiveColorLight(kWindowsColorSet.activeLight); + static QColor frameBorderActiveColorDark(kWindowsColorSet.activeDark); + pen.setColor(dark ? frameBorderActiveColorDark : frameBorderActiveColorLight); + } + } else { + static QColor frameBorderInactiveColorLight(kWindowsColorSet.inactiveLight); + static QColor frameBorderInactiveColorDark(kWindowsColorSet.inactiveDark); + pen.setColor(dark ? frameBorderInactiveColorDark : frameBorderInactiveColorLight); + } + painter.save(); + + // ### TODO: do we need to enable or disable it? + painter.setRenderHint(QPainter::Antialiasing); + + painter.setPen(pen); + painter.drawLine(QLine{ + QPoint{0, 0}, + QPoint{m_window->width(), 0} + }); + painter.restore(); + } + } -- Gitblit v1.9.1