diff --git a/framelesshelper_global.h b/framelesshelper_global.h index 3cb1742..48c99f2 100644 --- a/framelesshelper_global.h +++ b/framelesshelper_global.h @@ -67,6 +67,7 @@ namespace _flh_global { [[maybe_unused]] const char _flh_ignoredObjects_flag[] = "_FRAMELESSHELPER_WINDOW_TITLE_BAR_IGNORED_OBJECTS"; [[maybe_unused]] const char _flh_acrylic_blurEnabled_flag[] = "_FRAMELESSHELPER_BLUR_ENABLED"; [[maybe_unused]] const char _flh_acrylic_blurMode_flag[] = "_FRAMELESSHELPER_BLUR_MODE"; +[[maybe_unused]] const char _flh_acrylic_gradientColor_flag[] = "_FRAMELESSHELPER_BLUR_GRADIENT_COLOR"; [[maybe_unused]] const char _flh_acrylic_forceEnableOfficialMSWin10AcrylicBlur_flag[] = "_FRAMELESSHELPER_FORCE_ENABLE_MSWIN10_OFFICIAL_ACRYLIC_BLUR"; [[maybe_unused]] const char _flh_acrylic_forceEnableTraditionalBlur_flag[] = "_FRAMELESSHELPER_FORCE_ENABLE_TRADITIONAL_BLUR"; [[maybe_unused]] const char _flh_acrylic_forceDisableWallpaperBlur_flag[] = "_FRAMELESSHELPER_FORCE_DISABLE_WALLPAPER_BLUR"; diff --git a/framelesshelper_win32.cpp b/framelesshelper_win32.cpp index 5cdb984..c2e19ac 100644 --- a/framelesshelper_win32.cpp +++ b/framelesshelper_win32.cpp @@ -593,7 +593,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me POINT winLocalMouse = {qRound(globalMouse.x()), qRound(globalMouse.y())}; ScreenToClient(msg->hwnd, &winLocalMouse); const QPointF localMouse = {static_cast(winLocalMouse.x), static_cast(winLocalMouse.y)}; - const bool isInIgnoreObjects = isInSpecificObjects(globalMouse, qvariant_cast(window->property(_flh_global::_flh_ignoredObjects_flag)), dpr); + const bool isInIgnoreObjects = isInSpecificObjects(globalMouse, getIgnoredObjects(window), dpr); const int bh = getSystemMetric(window, Utilities::SystemMetric::BorderHeight, true); const int tbh = getSystemMetric(window, Utilities::SystemMetric::TitleBarHeight, true); const bool isTitleBar = (localMouse.y() <= tbh) && !isInIgnoreObjects; @@ -636,8 +636,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me return HTCLIENT; } const bool isBottom = (localMouse.y() >= (wh - bh)); - // Make the border a little wider to let the user easy to resize - // on corners. + // Make the border a little wider to let the user easy to resize on corners. const int factor = (isTop || isBottom) ? 2 : 1; const bool isLeft = (localMouse.x() <= (bw * factor)); const bool isRight = (localMouse.x() >= (ww - (bw * factor))); @@ -711,6 +710,36 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me default: break; } + // TODO: what if the user want to use the wallpaper blur all the time? + // Add an option to let the user choose what he wants. + if (Utilities::isWin10OrGreater()) { + if (window->property(_flh_global::_flh_acrylic_blurEnabled_flag).toBool()) { + bool shouldSwitchBlurMode = false; + if (msg->message == WM_ENTERSIZEMOVE) { + shouldSwitchBlurMode = true; + // Switch to the wallpaper blur temporarily due to the following issue: + // the window will become **VERY** laggy when it's being moved or resized. + // It's known as a bug of the API itself, currently no one knows how to fix it. + qunsetenv(_flh_global::_flh_acrylic_forceDisableWallpaperBlur_flag); + qunsetenv(_flh_global::_flh_acrylic_forceEnableTraditionalBlur_flag); + qunsetenv(_flh_global::_flh_acrylic_forceEnableOfficialMSWin10AcrylicBlur_flag); + } + if (msg->message == WM_EXITSIZEMOVE) { + shouldSwitchBlurMode = true; + // Switch back to the official Acrylic blur. That undocumented API won't cause any issues + // if we don't move or resize the window. + qputenv(_flh_global::_flh_acrylic_forceEnableTraditionalBlur_flag, "True"); + qputenv(_flh_global::_flh_acrylic_forceDisableWallpaperBlur_flag, "True"); + qputenv(_flh_global::_flh_acrylic_forceEnableOfficialMSWin10AcrylicBlur_flag, "True"); + } + if (shouldSwitchBlurMode) { + const auto gradientColor = qvariant_cast(window->property(_flh_global::_flh_acrylic_gradientColor_flag)); + if (!Utilities::setBlurEffectEnabled(window, true, gradientColor)) { + qWarning() << "Failed to enable the blur effect."; + } + } + } + } return false; } diff --git a/framelessquickhelper.cpp b/framelessquickhelper.cpp index 62566ca..d45c4ff 100644 --- a/framelessquickhelper.cpp +++ b/framelessquickhelper.cpp @@ -143,5 +143,11 @@ void FramelessQuickHelper::timerEvent(QTimerEvent *event) void FramelessQuickHelper::setBlurEffectEnabled(const bool enabled, const QColor &gradientColor) { +#ifdef Q_OS_WINDOWS + // TODO: let the user choose what he wants. + if (Utilities::isWin10OrGreater()) { + qputenv(_flh_global::_flh_acrylic_forceEnableOfficialMSWin10AcrylicBlur_flag, "True"); + } +#endif Utilities::setBlurEffectEnabled(window(), enabled, gradientColor); } diff --git a/qtacrylicwidget.cpp b/qtacrylicwidget.cpp index e535b44..2f608b9 100644 --- a/qtacrylicwidget.cpp +++ b/qtacrylicwidget.cpp @@ -145,6 +145,12 @@ void QtAcrylicWidget::showEvent(QShowEvent *event) if (!inited) { const QWindow *win = windowHandle(); FramelessWindowsManager::addWindow(win); +#ifdef Q_OS_WINDOWS + // TODO: let the user choose what he wants. + if (Utilities::isWin10OrGreater()) { + qputenv(_flh_global::_flh_acrylic_forceEnableOfficialMSWin10AcrylicBlur_flag, "True"); + } +#endif Utilities::setBlurEffectEnabled(win, true); m_acrylicHelper.install(win); m_acrylicHelper.updateAcrylicBrush(tintColor()); diff --git a/utilities_win32.cpp b/utilities_win32.cpp index 6b36963..53007ba 100644 --- a/utilities_win32.cpp +++ b/utilities_win32.cpp @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include #include @@ -291,8 +291,12 @@ bool Utilities::setBlurEffectEnabled(const QWindow *window, const bool enabled, if (!window) { return false; } - bool result = false; const auto hwnd = reinterpret_cast(window->winId()); + Q_ASSERT(hwnd); + if (!hwnd) { + return false; + } + bool result = false; // We prefer DwmEnableBlurBehindWindow on Windows 7. if (isWin8OrGreater() && win32Data()->SetWindowCompositionAttributePFN) { ACCENT_POLICY accentPolicy; @@ -339,6 +343,11 @@ bool Utilities::setBlurEffectEnabled(const QWindow *window, const bool enabled, qWarning() << "DwmEnableBlurBehindWindow failed."; } } + if (result) { + const auto win = const_cast(window); + win->setProperty(_flh_global::_flh_acrylic_blurEnabled_flag, enabled); + win->setProperty(_flh_global::_flh_acrylic_gradientColor_flag, gradientColor); + } return result; } @@ -397,6 +406,10 @@ bool Utilities::isDarkFrameEnabled(const QWindow *window) return false; } const auto hwnd = reinterpret_cast(window->winId()); + Q_ASSERT(hwnd); + if (!hwnd) { + return false; + } BOOL result = FALSE; const bool ok = SUCCEEDED(DwmGetWindowAttribute(hwnd, DwmwaUseImmersiveDarkMode, &result, sizeof(result))) || SUCCEEDED(DwmGetWindowAttribute(hwnd, DwmwaUseImmersiveDarkModeBefore20h1, &result, sizeof(result))); @@ -421,8 +434,12 @@ void Utilities::triggerFrameChange(const QWindow *window) if (!window) { return; } - if (SetWindowPos(reinterpret_cast(window->winId()), nullptr, 0, 0, 0, 0, - SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER) == FALSE) { + const auto hwnd = reinterpret_cast(window->winId()); + Q_ASSERT(hwnd); + if (!hwnd) { + return; + } + if (SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER) == FALSE) { qWarning() << "SetWindowPos failed."; } } @@ -433,8 +450,13 @@ void Utilities::updateFrameMargins(const QWindow *window, const bool reset) if (!window) { return; } + const auto hwnd = reinterpret_cast(window->winId()); + Q_ASSERT(hwnd); + if (!hwnd) { + return; + } const MARGINS margins = reset ? MARGINS{0, 0, 0, 0} : MARGINS{1, 1, 1, 1}; - if (FAILED(DwmExtendFrameIntoClientArea(reinterpret_cast(window->winId()), &margins))) { + if (FAILED(DwmExtendFrameIntoClientArea(hwnd, &margins))) { qWarning() << "DwmExtendFrameIntoClientArea failed."; } }