From 85edd9abbd5a9d86f7d091bac8c4bfe641eb4439 Mon Sep 17 00:00:00 2001 From: Yuhang Zhao <2546789017@qq.com> Date: Sun, 21 Mar 2021 15:47:18 +0800 Subject: [PATCH] Minor tweaks Signed-off-by: Yuhang Zhao <2546789017@qq.com> --- qtacryliceffecthelper.cpp | 12 +- utilities.h | 8 +- utilities_win32.cpp | 223 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 223 insertions(+), 20 deletions(-) diff --git a/qtacryliceffecthelper.cpp b/qtacryliceffecthelper.cpp index a31735e..fe5e9a5 100644 --- a/qtacryliceffecthelper.cpp +++ b/qtacryliceffecthelper.cpp @@ -322,17 +322,19 @@ void QtAcrylicEffectHelper::updateBehindWindowBackground() QImage buffer(size, QImage::Format_ARGB32_Premultiplied); #ifdef Q_OS_WINDOWS if (aspectStyle == Utilities::DesktopWallpaperAspectStyle::Central) { - buffer.fill(Qt::black); + buffer.fill(Utilities::getDesktopBackgroundColor()); } #endif - if (aspectStyle == Utilities::DesktopWallpaperAspectStyle::IgnoreRatio || - aspectStyle == Utilities::DesktopWallpaperAspectStyle::KeepRatio || + if (aspectStyle == Utilities::DesktopWallpaperAspectStyle::IgnoreRatioFill || + aspectStyle == Utilities::DesktopWallpaperAspectStyle::KeepRatioFill || aspectStyle == Utilities::DesktopWallpaperAspectStyle::KeepRatioByExpanding) { Qt::AspectRatioMode mode = Qt::KeepAspectRatioByExpanding; - if (aspectStyle == Utilities::DesktopWallpaperAspectStyle::IgnoreRatio) { + if (aspectStyle == Utilities::DesktopWallpaperAspectStyle::IgnoreRatioFill) { mode = Qt::IgnoreAspectRatio; - } else if (aspectStyle == Utilities::DesktopWallpaperAspectStyle::KeepRatio) { + } else if (aspectStyle == Utilities::DesktopWallpaperAspectStyle::KeepRatioFill) { mode = Qt::KeepAspectRatio; + } else { + mode = Qt::KeepAspectRatioByExpanding; } QSize newSize = image.size(); newSize.scale(size, mode); diff --git a/utilities.h b/utilities.h index d9ab627..92dca66 100644 --- a/utilities.h +++ b/utilities.h @@ -41,9 +41,10 @@ enum class DesktopWallpaperAspectStyle { Central, Tiled, - IgnoreRatio, - KeepRatio, - KeepRatioByExpanding + IgnoreRatioFill, // Stretch + KeepRatioFill, // Fit + KeepRatioByExpanding, // Fill + Span // Span }; // Common @@ -59,6 +60,7 @@ FRAMELESSHELPER_EXPORT bool isDarkThemeEnabled(); FRAMELESSHELPER_EXPORT QWindow *findWindow(const WId winId); FRAMELESSHELPER_EXPORT QImage getDesktopWallpaperImage(const int screen = -1); +FRAMELESSHELPER_EXPORT QColor getDesktopBackgroundColor(const int screen = -1); FRAMELESSHELPER_EXPORT DesktopWallpaperAspectStyle getDesktopWallpaperAspectStyle(const int screen = -1); FRAMELESSHELPER_EXPORT QRect getScreenAvailableGeometry(const QWindow *window); diff --git a/utilities_win32.cpp b/utilities_win32.cpp index 1ebe2dc..35178fa 100644 --- a/utilities_win32.cpp +++ b/utilities_win32.cpp @@ -36,7 +36,11 @@ #include #include #include +#include #include +#include +#include +#include #include #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) #include @@ -48,6 +52,9 @@ #else #include #endif +#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) +#include +#endif Q_DECLARE_METATYPE(QMargins) @@ -115,6 +122,7 @@ using PREFERRED_APP_MODE = enum _PREFERRED_APP_MODE static const QString g_dwmRegistryKey = QStringLiteral(R"(HKEY_CURRENT_USER\Software\Microsoft\Windows\DWM)"); static const QString g_personalizeRegistryKey = QStringLiteral(R"(HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)"); +static const QString g_desktopRegistryKey = QStringLiteral(R"(HKEY_CURRENT_USER\Control Panel\Desktop)"); // The standard values of border width, border height and title bar height when DPI is 96. static const int g_defaultBorderWidth = 8, g_defaultBorderHeight = 8, g_defaultTitleBarHeight = 31; @@ -480,34 +488,225 @@ void Utilities::updateFrameMargins(const QWindow *window, const bool reset) QImage Utilities::getDesktopWallpaperImage(const int screen) { - Q_UNUSED(screen); - WCHAR path[MAX_PATH]; - if (SystemParametersInfoW(SPI_GETDESKWALLPAPER, MAX_PATH, path, 0) == FALSE) { - qWarning() << "SystemParametersInfoW failed."; - return {}; + if (isWin8OrGreater()) { + if (SUCCEEDED(CoInitialize(nullptr))) { + IDesktopWallpaper* pDesktopWallpaper = nullptr; +#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) + const auto cleanup = qScopeGuard([pDesktopWallpaper](){ + if (pDesktopWallpaper) { + pDesktopWallpaper->Release(); + } + CoUninitialize(); + }); +#endif + if (SUCCEEDED(CoCreateInstance(CLSID_DesktopWallpaper, nullptr, CLSCTX_LOCAL_SERVER, IID_IDesktopWallpaper, reinterpret_cast(&pDesktopWallpaper))) && pDesktopWallpaper) { + UINT monitorCount = 0; + if (SUCCEEDED(pDesktopWallpaper->GetMonitorDevicePathCount(&monitorCount))) { + if (screen > int(monitorCount - 1)) { + qWarning() << "Screen number above total screen count."; + return {}; + } + const UINT monitorIndex = qMax(screen, 0); + LPWSTR monitorId = nullptr; + if (SUCCEEDED(pDesktopWallpaper->GetMonitorDevicePathAt(monitorIndex, &monitorId)) && monitorId) { + LPWSTR wallpaperPath = nullptr; + if (SUCCEEDED(pDesktopWallpaper->GetWallpaper(monitorId, &wallpaperPath)) && wallpaperPath) { + return QImage(QString::fromWCharArray(wallpaperPath)); + } else { + qWarning() << "IDesktopWallpaper::GetWallpaper() failed."; + } + } else { + qWarning() << "IDesktopWallpaper::GetMonitorDevicePathAt() failed"; + } + } else { + qWarning() << "IDesktopWallpaper::GetMonitorDevicePathCount() failed"; + } + } else { + qWarning() << "Failed to create COM instance - DesktopWallpaper."; + } + } else { + qWarning() << "Failed to initialize COM."; + } } - return QImage(QString::fromWCharArray(path)); + qDebug() << "The IDesktopWallpaper interface failed. Trying the IActiveDesktop interface instead."; + if (SUCCEEDED(CoInitialize(nullptr))) { + IActiveDesktop *pActiveDesktop = nullptr; +#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) + const auto cleanup = qScopeGuard([pActiveDesktop](){ + if (pActiveDesktop) { + pActiveDesktop->Release(); + } + CoUninitialize(); + }); +#endif + if (SUCCEEDED(CoCreateInstance(CLSID_ActiveDesktop, nullptr, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, reinterpret_cast(&pActiveDesktop))) && pActiveDesktop) { + PWSTR wallpaperPath = nullptr; + // AD_GETWP_BMP, AD_GETWP_IMAGE ??? + if (SUCCEEDED(pActiveDesktop->GetWallpaper(wallpaperPath, MAX_PATH, AD_GETWP_LAST_APPLIED)) && wallpaperPath) { + return QImage(QString::fromWCharArray(wallpaperPath)); + } else { + qWarning() << "IActiveDesktop::GetWallpaper() failed."; + } + } else { + qWarning() << "Failed to create COM instance - ActiveDesktop."; + } + } else { + qWarning() << "Failed to initialize COM."; + } + qDebug() << "Shell API failed. Using SystemParametersInfoW instead."; + LPWSTR wallpaperPath = nullptr; + if (SystemParametersInfoW(SPI_GETDESKWALLPAPER, MAX_PATH, wallpaperPath, 0) == TRUE) { + return QImage(QString::fromWCharArray(wallpaperPath)); + } + qWarning() << "SystemParametersInfoW failed. Reading from the registry instead."; + const QSettings settings(g_desktopRegistryKey, QSettings::NativeFormat); + const QString path = settings.value(QStringLiteral("WallPaper")).toString(); + if (QFileInfo::exists(path)) { + return QImage(path); + } + qWarning() << "Failed to read the registry."; + return {}; +} + +QColor Utilities::getDesktopBackgroundColor(const int screen) +{ + Q_UNUSED(screen); + if (isWin8OrGreater()) { + if (SUCCEEDED(CoInitialize(nullptr))) { + IDesktopWallpaper *pDesktopWallpaper = nullptr; +#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) + const auto cleanup = qScopeGuard([pDesktopWallpaper]() { + if (pDesktopWallpaper) { + pDesktopWallpaper->Release(); + } + CoUninitialize(); + }); +#endif + if (SUCCEEDED(CoCreateInstance(CLSID_DesktopWallpaper, nullptr, CLSCTX_LOCAL_SERVER, IID_IDesktopWallpaper, reinterpret_cast(&pDesktopWallpaper))) && pDesktopWallpaper) { + COLORREF color = 0; + if (SUCCEEDED(pDesktopWallpaper->GetBackgroundColor(&color))) { + return QColor::fromRgba(color); + } else { + qWarning() << "IDesktopWallpaper::GetBackgroundColor() failed."; + } + } else { + qWarning() << "Failed to create COM instance - DesktopWallpaper."; + } + } else { + qWarning() << "Failed to initialize COM."; + } + } + qDebug() << "The IDesktopWallpaper interface failed."; + return Qt::black; } Utilities::DesktopWallpaperAspectStyle Utilities::getDesktopWallpaperAspectStyle(const int screen) { Q_UNUSED(screen); - const QSettings settings(QStringLiteral(R"(HKEY_CURRENT_USER\Control Panel\Desktop)"), QSettings::NativeFormat); - const DWORD style = settings.value(QStringLiteral("WallpaperStyle")).toULongLong(); + if (isWin8OrGreater()) { + if (SUCCEEDED(CoInitialize(nullptr))) { + IDesktopWallpaper *pDesktopWallpaper = nullptr; +#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) + const auto cleanup = qScopeGuard([pDesktopWallpaper](){ + if (pDesktopWallpaper) { + pDesktopWallpaper->Release(); + } + CoUninitialize(); + }); +#endif + if (SUCCEEDED(CoCreateInstance(CLSID_DesktopWallpaper, nullptr, CLSCTX_LOCAL_SERVER, IID_IDesktopWallpaper, reinterpret_cast(&pDesktopWallpaper))) && pDesktopWallpaper) { + DESKTOP_WALLPAPER_POSITION position = DWPOS_FILL; + if (SUCCEEDED(pDesktopWallpaper->GetPosition(&position))) { + switch (position) { + case DWPOS_CENTER: + return DesktopWallpaperAspectStyle::Central; + case DWPOS_TILE: + return DesktopWallpaperAspectStyle::Tiled; + case DWPOS_STRETCH: + return DesktopWallpaperAspectStyle::IgnoreRatioFill; + case DWPOS_FIT: + return DesktopWallpaperAspectStyle::KeepRatioFill; + case DWPOS_FILL: + return DesktopWallpaperAspectStyle::KeepRatioByExpanding; + case DWPOS_SPAN: + return DesktopWallpaperAspectStyle::Span; + } + } else { + qWarning() << "IDesktopWallpaper::GetPosition() failed."; + } + } else { + qWarning() << "Failed to create COM instance - DesktopWallpaper."; + } + } else { + qWarning() << "Failed to initialize COM."; + } + } + qDebug() << "The IDesktopWallpaper interface failed. Trying the IActiveDesktop interface instead."; + if (SUCCEEDED(CoInitialize(nullptr))) { + IActiveDesktop *pActiveDesktop = nullptr; +#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) + const auto cleanup = qScopeGuard([pActiveDesktop](){ + if (pActiveDesktop) { + pActiveDesktop->Release(); + } + CoUninitialize(); + }); +#endif + if (SUCCEEDED(CoCreateInstance(CLSID_ActiveDesktop, nullptr, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, reinterpret_cast(&pActiveDesktop))) && pActiveDesktop) { + WALLPAPEROPT opt; + SecureZeroMemory(&opt, sizeof(opt)); + opt.dwSize = sizeof(opt); + if (SUCCEEDED(pActiveDesktop->GetWallpaperOptions(&opt, 0))) { + switch (opt.dwStyle) { + case WPSTYLE_CENTER: + return DesktopWallpaperAspectStyle::Central; + case WPSTYLE_TILE: + return DesktopWallpaperAspectStyle::Tiled; + case WPSTYLE_STRETCH: + return DesktopWallpaperAspectStyle::IgnoreRatioFill; + case WPSTYLE_KEEPASPECT: + return DesktopWallpaperAspectStyle::KeepRatioFill; + case WPSTYLE_CROPTOFIT: + return DesktopWallpaperAspectStyle::KeepRatioByExpanding; + case WPSTYLE_SPAN: + return DesktopWallpaperAspectStyle::Span; + } + } else { + qWarning() << "IActiveDesktop::GetWallpaperOptions() failed."; + } + } else { + qWarning() << "Failed to create COM instance - ActiveDesktop."; + } + } else { + qWarning() << "Failed to initialize COM."; + } + qDebug() << "Shell API failed. Reading from the registry instead."; + const QSettings settings(g_desktopRegistryKey, QSettings::NativeFormat); + bool ok = false; + const DWORD style = settings.value(QStringLiteral("WallpaperStyle"), 0).toULongLong(&ok); + if (!ok) { + qWarning() << "Failed to read the registry."; + return DesktopWallpaperAspectStyle::KeepRatioByExpanding; // Fill + } switch (style) { case 0: { - if (settings.value(QStringLiteral("TileWallpaper")).toBool()) { + bool ok = false; + if ((settings.value(QStringLiteral("TileWallpaper"), 0).toULongLong(&ok) != 0) && ok) { return DesktopWallpaperAspectStyle::Tiled; } else { return DesktopWallpaperAspectStyle::Central; } } case 2: - return DesktopWallpaperAspectStyle::IgnoreRatio; + return DesktopWallpaperAspectStyle::IgnoreRatioFill; case 6: - return DesktopWallpaperAspectStyle::KeepRatio; - default: + return DesktopWallpaperAspectStyle::KeepRatioFill; + case 10: return DesktopWallpaperAspectStyle::KeepRatioByExpanding; + case 22: + return DesktopWallpaperAspectStyle::Span; + default: + return DesktopWallpaperAspectStyle::KeepRatioByExpanding; // Fill } }