win: use Qt functionalities as much as possible

If Qt provides the functionalities we need, use it
instead of reinventing the wheel.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2022-08-16 15:24:14 +08:00
parent 3dbeb2721a
commit 0535276f55
9 changed files with 294 additions and 25 deletions

View File

@ -348,6 +348,23 @@ enum class WallpaperAspectStyle
};
Q_ENUM_NS(WallpaperAspectStyle)
#ifdef Q_OS_WINDOWS
enum class RegistryRootKey
{
ClassesRoot = 0,
CurrentUser = 1,
LocalMachine = 2,
Users = 3,
PerformanceData = 4,
CurrentConfig = 5,
DynData = 6,
CurrentUserLocalSettings = 7,
PerformanceText = 8,
PerformanceNlsText = 9
};
Q_ENUM_NS(RegistryRootKey)
#endif // Q_OS_WINDOWS
struct VersionNumber
{
int major = 0;

View File

@ -0,0 +1,66 @@
/*
* MIT License
*
* Copyright (C) 2022 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#include "framelesshelpercore_global.h"
#include <QtCore/qobject.h>
QT_BEGIN_NAMESPACE
class QWinRegistryKey;
class QSettings;
QT_END_NAMESPACE
FRAMELESSHELPER_BEGIN_NAMESPACE
class FRAMELESSHELPER_CORE_API Registry : public QObject
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(Registry)
public:
explicit Registry(const Global::RegistryRootKey root, const QString &key, QObject *parent = nullptr);
~Registry() override;
Q_NODISCARD Global::RegistryRootKey rootKey() const;
Q_NODISCARD QString subKey() const;
Q_NODISCARD bool isValid() const;
Q_NODISCARD QVariant value(const QString &name) const;
private:
Global::RegistryRootKey m_rootKey = Global::RegistryRootKey::CurrentUser;
QString m_subKey = {};
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QScopedPointer<QWinRegistryKey> m_registry;
#else
QScopedPointer<QSettings> m_settings;
bool m_valid = false;
#endif
};
FRAMELESSHELPER_END_NAMESPACE
Q_DECLARE_METATYPE2(FRAMELESSHELPER_PREPEND_NAMESPACE(Registry))

View File

@ -154,7 +154,6 @@ struct FRAMELESSHELPER_QUICK_API QuickGlobal
FRAMELESSHELPER_QUICK_ENUM_VALUE(WindowsVersion, Latest)
};
Q_ENUM(WindowsVersion)
static_assert(static_cast<int>(WindowsVersion::Latest) == static_cast<int>(Global::WindowsVersion::Latest));
#endif // Q_OS_WINDOWS
enum class ApplicationType

View File

@ -85,7 +85,11 @@ if(WIN32)
${INCLUDE_PREFIX}/FramelessHelper_Windows
${INCLUDE_PREFIX}/FramelessHelper_Win
)
list(APPEND PRIVATE_HEADERS
${INCLUDE_PREFIX}/private/registry_p.h
)
list(APPEND SOURCES
registry.cpp
utils_win.cpp
framelesshelper_win.cpp
)

View File

@ -36,6 +36,9 @@
#include "framelessconfig_p.h"
#include "chromepalette_p.h"
#include "micamaterial_p.h"
#ifdef Q_OS_WINDOWS
# include "registry_p.h"
#endif
#include <QtGui/qguiapplication.h>
#ifndef COMPILER_STRING
@ -153,6 +156,9 @@ void initialize()
qRegisterMetaType<ApplicationType>();
qRegisterMetaType<BlurMode>();
qRegisterMetaType<WallpaperAspectStyle>();
# ifdef Q_OS_WINDOWS
qRegisterMetaType<RegistryRootKey>();
# endif
qRegisterMetaType<VersionNumber>();
qRegisterMetaType<SystemParameters>();
qRegisterMetaType<VersionInfo>();
@ -169,6 +175,9 @@ void initialize()
qRegisterMetaType<ChromePalettePrivate>();
qRegisterMetaType<MicaMaterial>();
qRegisterMetaType<MicaMaterialPrivate>();
# ifdef Q_OS_WINDOWS
qRegisterMetaType<Registry>();
# endif
#endif
}

131
src/core/registry.cpp Normal file
View File

@ -0,0 +1,131 @@
/*
* MIT License
*
* Copyright (C) 2022 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "registry_p.h"
#include <QtCore/qdebug.h>
#include <QtCore/qvariant.h>
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
# include <QtCore/private/qwinregistry_p.h>
#else
# include <QtCore/qsettings.h>
#endif
FRAMELESSHELPER_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcCoreRegistry, "wangwenx190.framelesshelper.core.registry")
#define INFO qCInfo(lcCoreRegistry)
#define DEBUG qCDebug(lcCoreRegistry)
#define WARNING qCWarning(lcCoreRegistry)
#define CRITICAL qCCritical(lcCoreRegistry)
using namespace Global;
static const HKEY g_keyMap[] = {
HKEY_CLASSES_ROOT,
HKEY_CURRENT_USER,
HKEY_LOCAL_MACHINE,
HKEY_USERS,
HKEY_PERFORMANCE_DATA,
HKEY_CURRENT_CONFIG,
HKEY_DYN_DATA,
HKEY_CURRENT_USER_LOCAL_SETTINGS,
HKEY_PERFORMANCE_TEXT,
HKEY_PERFORMANCE_NLSTEXT
};
static_assert(std::size(g_keyMap) == (static_cast<int>(RegistryRootKey::PerformanceNlsText) + 1));
static const QString g_strMap[] = {
FRAMELESSHELPER_STRING_LITERAL("HKEY_CLASSES_ROOT"),
FRAMELESSHELPER_STRING_LITERAL("HKEY_CURRENT_USER"),
FRAMELESSHELPER_STRING_LITERAL("HKEY_LOCAL_MACHINE"),
FRAMELESSHELPER_STRING_LITERAL("HKEY_USERS"),
FRAMELESSHELPER_STRING_LITERAL("HKEY_PERFORMANCE_DATA"),
FRAMELESSHELPER_STRING_LITERAL("HKEY_CURRENT_CONFIG"),
FRAMELESSHELPER_STRING_LITERAL("HKEY_DYN_DATA"),
FRAMELESSHELPER_STRING_LITERAL("HKEY_CURRENT_USER_LOCAL_SETTINGS"),
FRAMELESSHELPER_STRING_LITERAL("HKEY_PERFORMANCE_TEXT"),
FRAMELESSHELPER_STRING_LITERAL("HKEY_PERFORMANCE_NLSTEXT")
};
static_assert(std::size(g_strMap) == std::size(g_keyMap));
Registry::Registry(const RegistryRootKey root, const QString &key, QObject *parent) : QObject(parent)
{
Q_ASSERT(!key.isEmpty());
if (key.isEmpty()) {
return;
}
m_rootKey = root;
m_subKey = key;
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
m_registry.reset(new QWinRegistryKey(g_keyMap[static_cast<int>(m_rootKey)], m_subKey));
#else
const QString rootKey = g_strMap[static_cast<int>(m_rootKey)];
m_settings.reset(new QSettings(rootKey, QSettings::NativeFormat));
if (m_settings->contains(m_subKey)) {
m_settings.reset(new QSettings(rootKey + u'\\' + m_subKey, QSettings::NativeFormat));
m_valid = true;
}
#endif
}
Registry::~Registry() = default;
RegistryRootKey Registry::rootKey() const
{
return m_rootKey;
}
QString Registry::subKey() const
{
return m_subKey;
}
bool Registry::isValid() const
{
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
return m_registry->isValid();
#else
return m_valid;
#endif
}
QVariant Registry::value(const QString &name) const
{
Q_ASSERT(!name.isEmpty());
Q_ASSERT(isValid());
if (name.isEmpty() || !isValid()) {
return {};
}
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
const QPair<DWORD, bool> dwValue = m_registry->dwordValue(name);
if (dwValue.second) {
return qulonglong(dwValue.first);
}
return m_registry->stringValue(name);
#else
return m_settings->value(name);
#endif
}
FRAMELESSHELPER_END_NAMESPACE

1
src/core/registry_p.h Normal file
View File

@ -0,0 +1 @@
#include "../../include/FramelessHelper/Core/private/registry_p.h"

View File

@ -26,8 +26,11 @@
#include <QtCore/qdebug.h>
#include <QtCore/qmutex.h>
#include <QtCore/qhash.h>
#include <QtCore/qsettings.h>
#include <QtCore/private/qsystemerror_p.h>
#include <QtGui/qguiapplication.h>
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
# include <QtGui/private/qguiapplication_p.h>
#endif
#include <QtGui/qpa/qplatformwindow.h>
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
# include <QtGui/qpa/qplatformnativeinterface.h>
@ -38,6 +41,7 @@
#include "framelesshelper_windows.h"
#include "framelessconfig_p.h"
#include "sysapiloader_p.h"
#include "registry_p.h"
#include <uxtheme.h>
#include <d2d1.h>
@ -270,27 +274,21 @@ private:
const std::wstring _Class = {};
};
[[nodiscard]] static inline QString hkcuRegistryKey()
{
static const QString key = FRAMELESSHELPER_STRING_LITERAL("HKEY_CURRENT_USER");
return key;
}
[[nodiscard]] static inline QString dwmRegistryKey()
{
static const QString key = (hkcuRegistryKey() + u'\\' + QString::fromWCharArray(kDwmRegistryKey));
static const QString key = QString::fromWCharArray(kDwmRegistryKey);
return key;
}
[[nodiscard]] static inline QString personalizeRegistryKey()
{
static const QString key = (hkcuRegistryKey() + u'\\' + QString::fromWCharArray(kPersonalizeRegistryKey));
static const QString key = QString::fromWCharArray(kPersonalizeRegistryKey);
return key;
}
[[nodiscard]] static inline QString desktopRegistryKey()
{
static const QString key = (hkcuRegistryKey() + u'\\' + QString::fromWCharArray(kDesktopRegistryKey));
static const QString key = QString::fromWCharArray(kDesktopRegistryKey);
return key;
}
@ -377,6 +375,7 @@ private:
if (code == ERROR_SUCCESS) {
return kSuccessMessageText;
}
#if 0
LPWSTR buf = nullptr;
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPWSTR>(&buf), 0, nullptr) == 0) {
@ -385,6 +384,9 @@ private:
const QString errorText = QString::fromWCharArray(buf).trimmed();
LocalFree(buf);
buf = nullptr;
#else
const QString errorText = QSystemError::windowsString(code);
#endif
return kErrorMessageTemplate.arg(function, QString::number(code), errorText);
}
@ -605,7 +607,10 @@ bool Utils::isDwmCompositionEnabled()
return true;
}
const auto resultFromRegistry = []() -> bool {
const QSettings registry(dwmRegistryKey(), QSettings::NativeFormat);
const Registry registry(RegistryRootKey::CurrentUser, dwmRegistryKey());
if (!registry.isValid()) {
return false;
}
bool ok = false;
const DWORD value = registry.value(kComposition).toULongLong(&ok);
return (ok && (value != 0));
@ -691,7 +696,12 @@ void Utils::updateInternalWindowFrameMargins(QWindow *window, const bool enable)
window->setProperty("_q_windowsCustomMargins", marginsVar);
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
if (QPlatformWindow *platformWindow = window->handle()) {
QGuiApplication::platformNativeInterface()->setWindowProperty(platformWindow, kWindowsCustomMargins, marginsVar);
if (const auto ni = QGuiApplication::platformNativeInterface()) {
ni->setWindowProperty(platformWindow, kWindowsCustomMargins, marginsVar);
} else {
WARNING << "Failed to retrieve the platform native interface.";
return;
}
} else {
WARNING << "Failed to retrieve the platform window.";
return;
@ -723,7 +733,10 @@ QString Utils::getSystemErrorMessage(const QString &function)
QColor Utils::getDwmColorizationColor()
{
const auto resultFromRegistry = []() -> QColor {
const QSettings registry(dwmRegistryKey(), QSettings::NativeFormat);
const Registry registry(RegistryRootKey::CurrentUser, dwmRegistryKey());
if (!registry.isValid()) {
return kDefaultDarkGrayColor;
}
bool ok = false;
const DWORD value = registry.value(kColorizationColor).toULongLong(&ok);
return (ok ? QColor::fromRgba(value) : kDefaultDarkGrayColor);
@ -748,12 +761,12 @@ DwmColorizationArea Utils::getDwmColorizationArea()
if (!isWin10OrGreater) {
return DwmColorizationArea::None_;
}
const QSettings themeRegistry(personalizeRegistryKey(), QSettings::NativeFormat);
const Registry themeRegistry(RegistryRootKey::CurrentUser, personalizeRegistryKey());
bool themeOk = false;
const DWORD themeValue = themeRegistry.value(qDwmColorKeyName).toULongLong(&themeOk);
const QSettings dwmRegistry(dwmRegistryKey(), QSettings::NativeFormat);
const DWORD themeValue = themeRegistry.isValid() ? themeRegistry.value(qDwmColorKeyName).toULongLong(&themeOk) : 0;
const Registry dwmRegistry(RegistryRootKey::CurrentUser, dwmRegistryKey());
bool dwmOk = false;
const DWORD dwmValue = dwmRegistry.value(qDwmColorKeyName).toULongLong(&dwmOk);
const DWORD dwmValue = dwmRegistry.isValid() ? dwmRegistry.value(qDwmColorKeyName).toULongLong(&dwmOk) : 0;
const bool theme = (themeOk && (themeValue != 0));
const bool dwm = (dwmOk && (dwmValue != 0));
if (theme && dwm) {
@ -1548,8 +1561,24 @@ bool Utils::shouldAppsUseDarkMode_windows()
if (!isWin10RS1OrGreater) {
return false;
}
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
if (const auto app = qApp->nativeInterface<QNativeInterface::Private::QWindowsApplication>()) {
return app->isDarkMode();
} else {
WARNING << "QWindowsApplication is not available.";
}
#elif (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
if (const auto ni = QGuiApplication::platformNativeInterface()) {
return ni->property("darkMode").toBool();
} else {
WARNING << "Failed to retrieve the platform native interface.";
}
#endif
const auto resultFromRegistry = []() -> bool {
const QSettings registry(personalizeRegistryKey(), QSettings::NativeFormat);
const Registry registry(RegistryRootKey::CurrentUser, personalizeRegistryKey());
if (!registry.isValid()) {
return false;
}
bool ok = false;
const DWORD value = registry.value(kAppsUseLightTheme).toULongLong(&ok);
return (ok && (value == 0));
@ -1780,7 +1809,10 @@ QColor Utils::getDwmAccentColor()
// so we'd better also do the same thing.
// There's no Windows API to get this value, so we can only read it
// directly from the registry.
const QSettings registry(dwmRegistryKey(), QSettings::NativeFormat);
const Registry registry(RegistryRootKey::CurrentUser, dwmRegistryKey());
if (!registry.isValid()) {
return kDefaultDarkGrayColor;
}
bool ok = false;
const DWORD value = registry.value(kAccentColor).toULongLong(&ok);
if (!ok) {
@ -1805,7 +1837,10 @@ QString Utils::getWallpaperFilePath()
WallpaperAspectStyle Utils::getWallpaperAspectStyle()
{
static constexpr const auto defaultStyle = WallpaperAspectStyle::Fill;
const QSettings registry(desktopRegistryKey(), QSettings::NativeFormat);
const Registry registry(RegistryRootKey::CurrentUser, desktopRegistryKey());
if (!registry.isValid()) {
return defaultStyle;
}
bool ok = false;
const DWORD wallpaperStyle = registry.value(kWallpaperStyle).toULongLong(&ok);
if (!ok) {

View File

@ -88,14 +88,21 @@ void FramelessHelper::Quick::registerTypes(QQmlEngine *engine)
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
qRegisterMetaType<FramelessQuickUtils>();
qRegisterMetaType<FramelessQuickUtils *>();
qRegisterMetaType<QuickChromePalette>();
qRegisterMetaType<QuickChromePalette *>();
qRegisterMetaType<FramelessQuickHelper>();
qRegisterMetaType<QuickStandardSystemButton>();
qRegisterMetaType<QuickStandardTitleBar>();
qRegisterMetaType<FramelessQuickWindow>();
qRegisterMetaType<FramelessQuickWindowPrivate>();
qRegisterMetaType<FramelessQuickHelper *>();
qRegisterMetaType<FramelessQuickHelperPrivate>();
qRegisterMetaType<QuickStandardSystemButton>();
qRegisterMetaType<QuickStandardSystemButton *>();
qRegisterMetaType<QuickStandardTitleBar>();
qRegisterMetaType<QuickStandardTitleBar *>();
qRegisterMetaType<FramelessQuickWindow>();
qRegisterMetaType<FramelessQuickWindow *>();
qRegisterMetaType<FramelessQuickWindowPrivate>();
qRegisterMetaType<QuickMicaMaterial>();
qRegisterMetaType<QuickMicaMaterial *>();
qRegisterMetaType<QuickMicaMaterialPrivate>();
#endif // (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))