From 3791802d3bd2e4deddbf8c4a663eae3730ba2d83 Mon Sep 17 00:00:00 2001 From: Yuhang Zhao <2546789017@qq.com> Date: Wed, 16 Nov 2022 14:10:49 +0800 Subject: [PATCH] win: add support for mica alt and other tweaks Add some more comments to the windows header. Remove the usages of UseRoundWindowCorner. Signed-off-by: Yuhang Zhao <2546789017@qq.com> --- examples/dialog/main.cpp | 1 - examples/mainwindow/main.cpp | 1 - examples/openglwidget/main.cpp | 1 - examples/quick/main.cpp | 1 - examples/widget/main.cpp | 1 - .../Core/framelesshelper_windows.h | 12 +++---- .../Core/framelesshelpercore_global.h | 13 ++++++-- include/FramelessHelper/Core/utils.h | 2 +- .../Quick/framelesshelperquick_global.h | 11 ++++++- src/core/framelesshelper_qt.cpp | 3 +- src/core/framelesshelper_win.cpp | 6 +--- src/core/framelesshelpercore_global.cpp | 1 + src/core/utils_win.cpp | 32 +++++++++++++------ src/quick/framelesshelperquick_global.cpp | 1 + src/quick/framelessquickhelper.cpp | 15 ++------- src/widgets/widgetssharedhelper.cpp | 20 +++--------- 16 files changed, 63 insertions(+), 58 deletions(-) diff --git a/examples/dialog/main.cpp b/examples/dialog/main.cpp index 37a63ff..b58497d 100644 --- a/examples/dialog/main.cpp +++ b/examples/dialog/main.cpp @@ -47,7 +47,6 @@ int main(int argc, char *argv[]) // a QGuiApplication instance. FramelessHelper::Core::setApplicationOSThemeAware(); - FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners); FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow); FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial); diff --git a/examples/mainwindow/main.cpp b/examples/mainwindow/main.cpp index d092867..62d124d 100644 --- a/examples/mainwindow/main.cpp +++ b/examples/mainwindow/main.cpp @@ -47,7 +47,6 @@ int main(int argc, char *argv[]) // a QGuiApplication instance. FramelessHelper::Core::setApplicationOSThemeAware(); - FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners); FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow); FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial); diff --git a/examples/openglwidget/main.cpp b/examples/openglwidget/main.cpp index e598a81..ff5ff61 100644 --- a/examples/openglwidget/main.cpp +++ b/examples/openglwidget/main.cpp @@ -84,7 +84,6 @@ int main(int argc, char *argv[]) // a QGuiApplication instance. FramelessHelper::Core::setApplicationOSThemeAware(); - FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners); FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow); FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial); diff --git a/examples/quick/main.cpp b/examples/quick/main.cpp index fc61363..e940a41 100644 --- a/examples/quick/main.cpp +++ b/examples/quick/main.cpp @@ -59,7 +59,6 @@ int main(int argc, char *argv[]) // a QGuiApplication instance. FramelessHelper::Core::setApplicationOSThemeAware(); - FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners); FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow); FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial); diff --git a/examples/widget/main.cpp b/examples/widget/main.cpp index 7ad406a..4de2ae6 100644 --- a/examples/widget/main.cpp +++ b/examples/widget/main.cpp @@ -47,7 +47,6 @@ int main(int argc, char *argv[]) // a QGuiApplication instance. FramelessHelper::Core::setApplicationOSThemeAware(); - FramelessConfig::instance()->set(Global::Option::WindowUseRoundCorners); FramelessConfig::instance()->set(Global::Option::EnableBlurBehindWindow); FramelessConfig::instance()->set(Global::Option::DisableLazyInitializationForMicaMaterial); diff --git a/include/FramelessHelper/Core/framelesshelper_windows.h b/include/FramelessHelper/Core/framelesshelper_windows.h index 0db2c79..d9c3792 100644 --- a/include/FramelessHelper/Core/framelesshelper_windows.h +++ b/include/FramelessHelper/Core/framelesshelper_windows.h @@ -302,12 +302,12 @@ using _DPI_AWARENESS = enum _DPI_AWARENESS using _DWMWINDOWATTRIBUTE = enum _DWMWINDOWATTRIBUTE { _DWMWA_USE_HOSTBACKDROPBRUSH = 17, // [set] BOOL, Allows the use of host backdrop brushes for the window. - _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19, // Undocumented + _DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19, // Undocumented, the same with DWMWA_USE_IMMERSIVE_DARK_MODE, but available on systems before Win10 20H1. _DWMWA_USE_IMMERSIVE_DARK_MODE = 20, // [set] BOOL, Allows a window to either use the accent color, or dark, according to the user Color Mode preferences. _DWMWA_WINDOW_CORNER_PREFERENCE = 33, // [set] WINDOW_CORNER_PREFERENCE, Controls the policy that rounds top-level window corners _DWMWA_VISIBLE_FRAME_BORDER_THICKNESS = 37, // [get] UINT, width of the visible border around a thick frame window _DWMWA_SYSTEMBACKDROP_TYPE = 38, // [get, set] SYSTEMBACKDROP_TYPE, Controls the system-drawn backdrop material of a window, including behind the non-client area. - _DWMWA_MICA_EFFECT = 1029 // Undocumented + _DWMWA_MICA_EFFECT = 1029 // Undocumented, use this value to enable Mica material on Win11 21H2. You should use DWMWA_SYSTEMBACKDROP_TYPE instead on Win11 22H2 and newer. }; using _DWM_WINDOW_CORNER_PREFERENCE = enum _DWM_WINDOW_CORNER_PREFERENCE @@ -410,10 +410,10 @@ using IMMERSIVE_HC_CACHE_MODE = enum IMMERSIVE_HC_CACHE_MODE using PREFERRED_APP_MODE = enum PREFERRED_APP_MODE { - PAM_DEFAULT = 0, // Use default behavior. - PAM_AUTO = 1, // Let system decide. - PAM_DARK = 2, // Force dark mode. - PAM_LIGHT = 3, // Force light mode. + PAM_DEFAULT = 0, // Default behavior on systems before Win10 1809. It indicates the application doesn't support dark mode at all. + PAM_AUTO = 1, // Available since Win10 1809, let system decide whether to enable dark mode or not. + PAM_DARK = 2, // Available since Win10 1903, force dark mode regardless of the system theme. + PAM_LIGHT = 3, // Available since Win10 1903, force light mode regardless of the system theme. PAM_MAX = 4 }; diff --git a/include/FramelessHelper/Core/framelesshelpercore_global.h b/include/FramelessHelper/Core/framelesshelpercore_global.h index e06d393..d05397e 100644 --- a/include/FramelessHelper/Core/framelesshelpercore_global.h +++ b/include/FramelessHelper/Core/framelesshelpercore_global.h @@ -347,7 +347,8 @@ enum class BlurMode Default = 1, // Use platform default blur mode Windows_Aero = 2, // Windows only, use the traditional DWM blur Windows_Acrylic = 3, // Windows only, use the Acrylic blur - Windows_Mica = 4 // Windows only, use the Mica material + Windows_Mica = 4, // Windows only, use the Mica material + Windows_MicaAlt = 5 // Windows only, use the Mica Alt material }; Q_ENUM_NS(BlurMode) @@ -379,7 +380,7 @@ enum class RegistryRootKey Q_ENUM_NS(RegistryRootKey) #endif // Q_OS_WINDOWS -enum class WindowEdge +enum class WindowEdge : quint32 { Left = 0x00000000, Top = 0x00000001, @@ -404,6 +405,14 @@ enum class DpiAwareness Q_ENUM_NS(DpiAwareness) #endif // Q_OS_WINDOWS +enum class WindowCornerStyle +{ + Default = 0, + Square = 1, + Round = 2 +}; +Q_ENUM_NS(WindowCornerStyle) + struct VersionNumber { int major = 0; diff --git a/include/FramelessHelper/Core/utils.h b/include/FramelessHelper/Core/utils.h index a0eed28..f7b7011 100644 --- a/include/FramelessHelper/Core/utils.h +++ b/include/FramelessHelper/Core/utils.h @@ -109,7 +109,7 @@ FRAMELESSHELPER_CORE_API void setAeroSnappingEnabled(const WId windowId, const b FRAMELESSHELPER_CORE_API void tryToEnableHighestDpiAwarenessLevel(); FRAMELESSHELPER_CORE_API void updateGlobalWin32ControlsTheme(const WId windowId, const bool dark); [[nodiscard]] FRAMELESSHELPER_CORE_API bool shouldAppsUseDarkMode_windows(); -FRAMELESSHELPER_CORE_API void forceSquareCornersForWindow(const WId windowId, const bool force); +FRAMELESSHELPER_CORE_API void setCornerStyleForWindow(const WId windowId, const Global::WindowCornerStyle style); [[nodiscard]] FRAMELESSHELPER_CORE_API QColor getDwmAccentColor(); FRAMELESSHELPER_CORE_API void hideOriginalTitleBarElements (const WId windowId, const bool disable = true); diff --git a/include/FramelessHelper/Quick/framelesshelperquick_global.h b/include/FramelessHelper/Quick/framelesshelperquick_global.h index eed453a..bc34fe8 100644 --- a/include/FramelessHelper/Quick/framelesshelperquick_global.h +++ b/include/FramelessHelper/Quick/framelesshelperquick_global.h @@ -186,10 +186,11 @@ public: FRAMELESSHELPER_QUICK_ENUM_VALUE(BlurMode, Windows_Aero) FRAMELESSHELPER_QUICK_ENUM_VALUE(BlurMode, Windows_Acrylic) FRAMELESSHELPER_QUICK_ENUM_VALUE(BlurMode, Windows_Mica) + FRAMELESSHELPER_QUICK_ENUM_VALUE(BlurMode, Windows_MicaAlt) }; Q_ENUM(BlurMode) - enum class WindowEdge + enum class WindowEdge : quint32 { FRAMELESSHELPER_QUICK_ENUM_VALUE(WindowEdge, Left) FRAMELESSHELPER_QUICK_ENUM_VALUE(WindowEdge, Top) @@ -199,6 +200,14 @@ public: Q_ENUM(WindowEdge) Q_DECLARE_FLAGS(WindowEdges, WindowEdge) Q_FLAG(WindowEdges) + + enum class WindowCornerStyle + { + FRAMELESSHELPER_QUICK_ENUM_VALUE(WindowCornerStyle, Default) + FRAMELESSHELPER_QUICK_ENUM_VALUE(WindowCornerStyle, Square) + FRAMELESSHELPER_QUICK_ENUM_VALUE(WindowCornerStyle, Round) + }; + Q_ENUM(WindowCornerStyle) }; Q_DECLARE_OPERATORS_FOR_FLAGS(QuickGlobal::WindowEdges) diff --git a/src/core/framelesshelper_qt.cpp b/src/core/framelesshelper_qt.cpp index f7bb7f3..f01737b 100644 --- a/src/core/framelesshelper_qt.cpp +++ b/src/core/framelesshelper_qt.cpp @@ -90,8 +90,7 @@ void FramelessHelperQt::addWindow(const SystemParameters ¶ms) g_qtHelper()->mutex.unlock(); const bool shouldApplyFramelessFlag = [¶ms]() -> bool { #ifdef Q_OS_MACOS - if (FramelessConfig::instance()->isSet(Option::WindowUseRoundCorners) - && (params.getCurrentApplicationType() == ApplicationType::Quick)) { + if (params.getCurrentApplicationType() == ApplicationType::Quick) { return false; } #else diff --git a/src/core/framelesshelper_win.cpp b/src/core/framelesshelper_win.cpp index 82dc992..e4a040e 100644 --- a/src/core/framelesshelper_win.cpp +++ b/src/core/framelesshelper_win.cpp @@ -559,13 +559,9 @@ void FramelessHelperWin::addWindow(const SystemParameters ¶ms) } Utils::refreshWin32ThemeResources(windowId, dark); if (WindowsVersionHelper::isWin11OrGreater()) { - const FramelessConfig * const config = FramelessConfig::instance(); - // Set the frame corner style, only Win11 provides official public API to do it. - // On Win7~Win10, you'll need to use SetWindowRgn(), which will break the frame shadow. - Utils::forceSquareCornersForWindow(windowId, !config->isSet(Option::WindowUseRoundCorners)); // The fallback title bar window is only used to activate the Snap Layout feature // introduced in Windows 11, so it's not necessary to create it on systems below Win11. - if (!config->isSet(Option::DisableWindowsSnapLayout)) { + if (!FramelessConfig::instance()->isSet(Option::DisableWindowsSnapLayout)) { if (!createFallbackTitleBarWindow(windowId, data.params.isWindowFixedSize())) { WARNING << "Failed to create the fallback title bar window."; } diff --git a/src/core/framelesshelpercore_global.cpp b/src/core/framelesshelpercore_global.cpp index 2aed3bd..9436c1f 100644 --- a/src/core/framelesshelpercore_global.cpp +++ b/src/core/framelesshelpercore_global.cpp @@ -202,6 +202,7 @@ void initialize() # ifdef Q_OS_WINDOWS qRegisterMetaType(); # endif + qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); diff --git a/src/core/utils_win.cpp b/src/core/utils_win.cpp index 04ea36d..a950a77 100644 --- a/src/core/utils_win.cpp +++ b/src/core/utils_win.cpp @@ -2214,7 +2214,7 @@ bool Utils::shouldAppsUseDarkMode_windows() return resultFromRegistry(); } -void Utils::forceSquareCornersForWindow(const WId windowId, const bool force) +void Utils::setCornerStyleForWindow(const WId windowId, const WindowCornerStyle style) { Q_ASSERT(windowId); if (!windowId) { @@ -2228,8 +2228,20 @@ void Utils::forceSquareCornersForWindow(const WId windowId, const bool force) return; } const auto hwnd = reinterpret_cast(windowId); - const _DWM_WINDOW_CORNER_PREFERENCE wcp = (force ? _DWMWCP_DONOTROUND : _DWMWCP_ROUND); - const HRESULT hr = API_CALL_FUNCTION(DwmSetWindowAttribute, hwnd, _DWMWA_WINDOW_CORNER_PREFERENCE, &wcp, sizeof(wcp)); + const auto wcp = [style]() -> _DWM_WINDOW_CORNER_PREFERENCE { + switch (style) { + case WindowCornerStyle::Default: + return _DWMWCP_DEFAULT; + case WindowCornerStyle::Square: + return _DWMWCP_DONOTROUND; + case WindowCornerStyle::Round: + return _DWMWCP_ROUND; + } + Q_ASSERT(false); + return _DWMWCP_DEFAULT; + }(); + const HRESULT hr = API_CALL_FUNCTION(DwmSetWindowAttribute, + hwnd, _DWMWA_WINDOW_CORNER_PREFERENCE, &wcp, sizeof(wcp)); if (FAILED(hr)) { WARNING << __getSystemErrorMessage(kDwmSetWindowAttribute, hr); } @@ -2256,11 +2268,13 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode, g_micaData()->mutex.unlock(); updateWindowFrameMargins(windowId, false); }; - const BlurMode blurMode = [mode]() -> BlurMode { + const bool preferMicaAlt = (qEnvironmentVariableIntValue("FRAMELESSHELPER_PREFER_MICA_ALT") != 0); + const BlurMode blurMode = [mode, preferMicaAlt]() -> BlurMode { if ((mode == BlurMode::Disable) || (mode == BlurMode::Windows_Aero)) { return mode; } - if ((mode == BlurMode::Windows_Mica) && !WindowsVersionHelper::isWin11OrGreater()) { + if (((mode == BlurMode::Windows_Mica) || (mode == BlurMode::Windows_MicaAlt)) + && !WindowsVersionHelper::isWin11OrGreater()) { WARNING << "The Mica material is not supported on your system, fallback to the Acrylic blur instead..."; if (WindowsVersionHelper::isWin10OrGreater()) { return BlurMode::Windows_Acrylic; @@ -2274,7 +2288,7 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode, } if (mode == BlurMode::Default) { if (WindowsVersionHelper::isWin11OrGreater()) { - return BlurMode::Windows_Mica; + return (preferMicaAlt ? BlurMode::Windows_MicaAlt : BlurMode::Windows_Mica); } if (WindowsVersionHelper::isWin10OrGreater()) { return BlurMode::Windows_Acrylic; @@ -2321,7 +2335,7 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode, } return result; } else { - if (blurMode == BlurMode::Windows_Mica) { + if ((blurMode == BlurMode::Windows_Mica) || (blurMode == BlurMode::Windows_MicaAlt)) { g_micaData()->mutex.lock(); if (!g_micaData()->windowIds.contains(windowId)) { g_micaData()->windowIds.append(windowId); @@ -2347,8 +2361,8 @@ bool Utils::setBlurBehindWindowEnabled(const WId windowId, const BlurMode mode, if (SUCCEEDED(hr)) { if (WindowsVersionHelper::isWin1122H2OrGreater()) { const auto dwmsbt = ( - qEnvironmentVariableIntValue("FRAMELESSHELPER_USE_MICA_ALT") - ? _DWMSBT_TABBEDWINDOW : _DWMSBT_MAINWINDOW); + ((blurMode == BlurMode::Windows_MicaAlt) || preferMicaAlt) + ? _DWMSBT_TABBEDWINDOW : _DWMSBT_MAINWINDOW); hr = API_CALL_FUNCTION(DwmSetWindowAttribute, hwnd, _DWMWA_SYSTEMBACKDROP_TYPE, &dwmsbt, sizeof(dwmsbt)); if (SUCCEEDED(hr)) { diff --git a/src/quick/framelesshelperquick_global.cpp b/src/quick/framelesshelperquick_global.cpp index e764601..305786c 100644 --- a/src/quick/framelesshelperquick_global.cpp +++ b/src/quick/framelesshelperquick_global.cpp @@ -90,6 +90,7 @@ void initialize() qRegisterMetaType(); qRegisterMetaType(); qRegisterMetaType(); + qRegisterMetaType(); #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) qRegisterMetaType(); diff --git a/src/quick/framelessquickhelper.cpp b/src/quick/framelessquickhelper.cpp index 16b3f03..03e124e 100644 --- a/src/quick/framelessquickhelper.cpp +++ b/src/quick/framelessquickhelper.cpp @@ -645,23 +645,14 @@ bool FramelessQuickHelperPrivate::eventFilter(QObject *object, QEvent *event) return QObject::eventFilter(object, event); } const auto window = qobject_cast(object); - const WId windowId = window->winId(); - const bool roundCorner = FramelessConfig::instance()->isSet(Option::WindowUseRoundCorners); #if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) - if (Utils::windowStatesToWindowState(window->windowStates()) == Qt::WindowFullScreen) { + if (Utils::windowStatesToWindowState(window->windowStates()) != Qt::WindowFullScreen) { #else - if (window->windowState() == Qt::WindowFullScreen) { + if (window->windowState() != Qt::WindowFullScreen) { #endif - if (WindowsVersionHelper::isWin11OrGreater() && roundCorner) { - Utils::forceSquareCornersForWindow(windowId, true); - } - } else { const auto changeEvent = static_cast(event); if (Utils::windowStatesToWindowState(changeEvent->oldState()) == Qt::WindowFullScreen) { - Utils::maybeFixupQtInternals(windowId); - if (WindowsVersionHelper::isWin11OrGreater() && roundCorner) { - Utils::forceSquareCornersForWindow(windowId, false); - } + Utils::maybeFixupQtInternals(window->winId()); } } #endif diff --git a/src/widgets/widgetssharedhelper.cpp b/src/widgets/widgetssharedhelper.cpp index 7d37652..346de2f 100644 --- a/src/widgets/widgetssharedhelper.cpp +++ b/src/widgets/widgetssharedhelper.cpp @@ -196,21 +196,11 @@ void WidgetsSharedHelper::changeEventHandler(QEvent *event) } } #ifdef Q_OS_WINDOWS - if (FramelessConfig::instance()->isSet(Option::UseCrossPlatformQtImplementation)) { - return; - } - const WId windowId = m_targetWidget->winId(); - const bool roundCorner = FramelessConfig::instance()->isSet(Option::WindowUseRoundCorners); - if (Utils::windowStatesToWindowState(m_targetWidget->windowState()) == Qt::WindowFullScreen) { - if (WindowsVersionHelper::isWin11OrGreater() && roundCorner) { - Utils::forceSquareCornersForWindow(windowId, true); - } - } else { - const auto changeEvent = static_cast(event); - if (Utils::windowStatesToWindowState(changeEvent->oldState()) == Qt::WindowFullScreen) { - Utils::maybeFixupQtInternals(windowId); - if (WindowsVersionHelper::isWin11OrGreater() && roundCorner) { - Utils::forceSquareCornersForWindow(windowId, false); + if (!FramelessConfig::instance()->isSet(Option::UseCrossPlatformQtImplementation)) { + if (Utils::windowStatesToWindowState(m_targetWidget->windowState()) != Qt::WindowFullScreen) { + const auto changeEvent = static_cast(event); + if (Utils::windowStatesToWindowState(changeEvent->oldState()) == Qt::WindowFullScreen) { + Utils::maybeFixupQtInternals(m_targetWidget->winId()); } } }