Use the official Acrylic blur whenever possible

And switch back to the wallpaper blur when the window is being moved or resized.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2021-03-10 17:28:48 +08:00
parent 54798e2f73
commit c9be4858ec
5 changed files with 72 additions and 8 deletions

View File

@ -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_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_blurEnabled_flag[] = "_FRAMELESSHELPER_BLUR_ENABLED";
[[maybe_unused]] const char _flh_acrylic_blurMode_flag[] = "_FRAMELESSHELPER_BLUR_MODE"; [[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_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_forceEnableTraditionalBlur_flag[] = "_FRAMELESSHELPER_FORCE_ENABLE_TRADITIONAL_BLUR";
[[maybe_unused]] const char _flh_acrylic_forceDisableWallpaperBlur_flag[] = "_FRAMELESSHELPER_FORCE_DISABLE_WALLPAPER_BLUR"; [[maybe_unused]] const char _flh_acrylic_forceDisableWallpaperBlur_flag[] = "_FRAMELESSHELPER_FORCE_DISABLE_WALLPAPER_BLUR";

View File

@ -593,7 +593,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
POINT winLocalMouse = {qRound(globalMouse.x()), qRound(globalMouse.y())}; POINT winLocalMouse = {qRound(globalMouse.x()), qRound(globalMouse.y())};
ScreenToClient(msg->hwnd, &winLocalMouse); ScreenToClient(msg->hwnd, &winLocalMouse);
const QPointF localMouse = {static_cast<qreal>(winLocalMouse.x), static_cast<qreal>(winLocalMouse.y)}; const QPointF localMouse = {static_cast<qreal>(winLocalMouse.x), static_cast<qreal>(winLocalMouse.y)};
const bool isInIgnoreObjects = isInSpecificObjects(globalMouse, qvariant_cast<QObjectList>(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 bh = getSystemMetric(window, Utilities::SystemMetric::BorderHeight, true);
const int tbh = getSystemMetric(window, Utilities::SystemMetric::TitleBarHeight, true); const int tbh = getSystemMetric(window, Utilities::SystemMetric::TitleBarHeight, true);
const bool isTitleBar = (localMouse.y() <= tbh) && !isInIgnoreObjects; const bool isTitleBar = (localMouse.y() <= tbh) && !isInIgnoreObjects;
@ -636,8 +636,7 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
return HTCLIENT; return HTCLIENT;
} }
const bool isBottom = (localMouse.y() >= (wh - bh)); const bool isBottom = (localMouse.y() >= (wh - bh));
// Make the border a little wider to let the user easy to resize // Make the border a little wider to let the user easy to resize on corners.
// on corners.
const int factor = (isTop || isBottom) ? 2 : 1; const int factor = (isTop || isBottom) ? 2 : 1;
const bool isLeft = (localMouse.x() <= (bw * factor)); const bool isLeft = (localMouse.x() <= (bw * factor));
const bool isRight = (localMouse.x() >= (ww - (bw * factor))); const bool isRight = (localMouse.x() >= (ww - (bw * factor)));
@ -711,6 +710,36 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
default: default:
break; 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<QColor>(window->property(_flh_global::_flh_acrylic_gradientColor_flag));
if (!Utilities::setBlurEffectEnabled(window, true, gradientColor)) {
qWarning() << "Failed to enable the blur effect.";
}
}
}
}
return false; return false;
} }

View File

@ -143,5 +143,11 @@ void FramelessQuickHelper::timerEvent(QTimerEvent *event)
void FramelessQuickHelper::setBlurEffectEnabled(const bool enabled, const QColor &gradientColor) 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); Utilities::setBlurEffectEnabled(window(), enabled, gradientColor);
} }

View File

@ -145,6 +145,12 @@ void QtAcrylicWidget::showEvent(QShowEvent *event)
if (!inited) { if (!inited) {
const QWindow *win = windowHandle(); const QWindow *win = windowHandle();
FramelessWindowsManager::addWindow(win); 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); Utilities::setBlurEffectEnabled(win, true);
m_acrylicHelper.install(win); m_acrylicHelper.install(win);
m_acrylicHelper.updateAcrylicBrush(tintColor()); m_acrylicHelper.updateAcrylicBrush(tintColor());

View File

@ -34,7 +34,7 @@
#include <QtCore/qsettings.h> #include <QtCore/qsettings.h>
#include <QtCore/qlibrary.h> #include <QtCore/qlibrary.h>
#include <QtCore/qt_windows.h> #include <QtCore/qt_windows.h>
#include <QtCore/qcoreapplication.h> #include <QtGui/qguiapplication.h>
#include <QtCore/qdebug.h> #include <QtCore/qdebug.h>
#include <dwmapi.h> #include <dwmapi.h>
#include <QtGui/qpa/qplatformwindow.h> #include <QtGui/qpa/qplatformwindow.h>
@ -291,8 +291,12 @@ bool Utilities::setBlurEffectEnabled(const QWindow *window, const bool enabled,
if (!window) { if (!window) {
return false; return false;
} }
bool result = false;
const auto hwnd = reinterpret_cast<HWND>(window->winId()); const auto hwnd = reinterpret_cast<HWND>(window->winId());
Q_ASSERT(hwnd);
if (!hwnd) {
return false;
}
bool result = false;
// We prefer DwmEnableBlurBehindWindow on Windows 7. // We prefer DwmEnableBlurBehindWindow on Windows 7.
if (isWin8OrGreater() && win32Data()->SetWindowCompositionAttributePFN) { if (isWin8OrGreater() && win32Data()->SetWindowCompositionAttributePFN) {
ACCENT_POLICY accentPolicy; ACCENT_POLICY accentPolicy;
@ -339,6 +343,11 @@ bool Utilities::setBlurEffectEnabled(const QWindow *window, const bool enabled,
qWarning() << "DwmEnableBlurBehindWindow failed."; qWarning() << "DwmEnableBlurBehindWindow failed.";
} }
} }
if (result) {
const auto win = const_cast<QWindow *>(window);
win->setProperty(_flh_global::_flh_acrylic_blurEnabled_flag, enabled);
win->setProperty(_flh_global::_flh_acrylic_gradientColor_flag, gradientColor);
}
return result; return result;
} }
@ -397,6 +406,10 @@ bool Utilities::isDarkFrameEnabled(const QWindow *window)
return false; return false;
} }
const auto hwnd = reinterpret_cast<HWND>(window->winId()); const auto hwnd = reinterpret_cast<HWND>(window->winId());
Q_ASSERT(hwnd);
if (!hwnd) {
return false;
}
BOOL result = FALSE; BOOL result = FALSE;
const bool ok = SUCCEEDED(DwmGetWindowAttribute(hwnd, DwmwaUseImmersiveDarkMode, &result, sizeof(result))) const bool ok = SUCCEEDED(DwmGetWindowAttribute(hwnd, DwmwaUseImmersiveDarkMode, &result, sizeof(result)))
|| SUCCEEDED(DwmGetWindowAttribute(hwnd, DwmwaUseImmersiveDarkModeBefore20h1, &result, sizeof(result))); || SUCCEEDED(DwmGetWindowAttribute(hwnd, DwmwaUseImmersiveDarkModeBefore20h1, &result, sizeof(result)));
@ -421,8 +434,12 @@ void Utilities::triggerFrameChange(const QWindow *window)
if (!window) { if (!window) {
return; return;
} }
if (SetWindowPos(reinterpret_cast<HWND>(window->winId()), nullptr, 0, 0, 0, 0, const auto hwnd = reinterpret_cast<HWND>(window->winId());
SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER) == FALSE) { 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."; qWarning() << "SetWindowPos failed.";
} }
} }
@ -433,8 +450,13 @@ void Utilities::updateFrameMargins(const QWindow *window, const bool reset)
if (!window) { if (!window) {
return; return;
} }
const auto hwnd = reinterpret_cast<HWND>(window->winId());
Q_ASSERT(hwnd);
if (!hwnd) {
return;
}
const MARGINS margins = reset ? MARGINS{0, 0, 0, 0} : MARGINS{1, 1, 1, 1}; const MARGINS margins = reset ? MARGINS{0, 0, 0, 0} : MARGINS{1, 1, 1, 1};
if (FAILED(DwmExtendFrameIntoClientArea(reinterpret_cast<HWND>(window->winId()), &margins))) { if (FAILED(DwmExtendFrameIntoClientArea(hwnd, &margins))) {
qWarning() << "DwmExtendFrameIntoClientArea failed."; qWarning() << "DwmExtendFrameIntoClientArea failed.";
} }
} }