From 08c49417849b71c79d64e9b219f637a7d2c42279 Mon Sep 17 00:00:00 2001 From: Duncan Ogilvie Date: Sun, 10 Jul 2022 15:04:53 +0200 Subject: [PATCH] Improve the code to automatically detect the initial theme --- src/gui/Src/Gui/MainWindow.cpp | 151 +++++++++++++++++++-------------- src/gui/Src/Gui/MainWindow.h | 2 +- src/gui/Src/main.cpp | 11 ++- 3 files changed, 97 insertions(+), 67 deletions(-) diff --git a/src/gui/Src/Gui/MainWindow.cpp b/src/gui/Src/Gui/MainWindow.cpp index 62205d1b..33835a54 100644 --- a/src/gui/Src/Gui/MainWindow.cpp +++ b/src/gui/Src/Gui/MainWindow.cpp @@ -483,75 +483,113 @@ static void importSettings(const QString & filename, const QSet & secti emit Config()->guiOptionsUpdated(); emit Config()->shortcutsUpdated(); emit Config()->tokenizerConfigUpdated(); - GuiUpdateAllViews(); + // Before startup we don't need to update all views + if(Bridge::getBridge()) + GuiUpdateAllViews(); } } } -void MainWindow::loadSelectedStyle(bool reloadStyleCss) +void MainWindow::loadSelectedTheme(bool reloadOnlyStyleCss) { - char selectedTheme[MAX_SETTING_SIZE] = ""; - QString stylePath(":/css/default.css"); - QString styleSettings; - if(!BridgeSettingGet("Theme", "Selected", selectedTheme)) + if(BridgeGetNtBuildNumber() >= 14393 /* darkmode registry release */) { - // First Run + duint lastAppsUseLightTheme = -1; + BridgeSettingGetUint("Theme", "AppsUseLightTheme", &lastAppsUseLightTheme); - // https://www.vergiliusproject.com/kernels/x64/Windows%2010%20%7C%202016/2009%2020H2%20(October%202020%20Update)/_KUSER_SHARED_DATA - uint32_t NtBuildNumber = *(uint32_t*)(0x7FFE0000 + 0x260); + auto readRegistryDword = [](HKEY hRootKey, const wchar_t* lpSubKey, const wchar_t* lpValueName, DWORD & result) + { + auto success = false; + HKEY hKey = 0; + if(RegOpenKeyExW(hRootKey, lpSubKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + DWORD dwBufferSize = sizeof(DWORD); + DWORD dwData = 0; + if(RegQueryValueExW(hKey, lpValueName, 0, NULL, reinterpret_cast(&dwData), &dwBufferSize) == ERROR_SUCCESS) + { + result = dwData; + success = true; + } + RegCloseKey(hKey); + } + return success; + }; - if(NtBuildNumber != 0 && NtBuildNumber >= 14393 /* darkmode registry release */) + DWORD appsUseLightTheme = 1; + auto subKey = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; + auto valueName = L"AppsUseLightTheme"; + if(!readRegistryDword(HKEY_CURRENT_USER, subKey, valueName, appsUseLightTheme)) + readRegistryDword(HKEY_LOCAL_MACHINE, subKey, valueName, appsUseLightTheme); + + // If the user changed the setting since last startup, adjust the default theme + if(appsUseLightTheme != lastAppsUseLightTheme) { - HKEY hKey; - RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", 0, KEY_READ, &hKey); - DWORD dwBufferSize(sizeof(DWORD)); - DWORD nResult(1); - RegQueryValueExW(hKey, - L"AppsUseLightTheme", - 0, - NULL, - reinterpret_cast(&nResult), - &dwBufferSize); - if(nResult == 0) - { - BridgeSettingSet("Theme", "Selected", QString("Dark").toUtf8().constData()); - strcpy_s(selectedTheme, MAX_SETTING_SIZE, "Dark"); - } - else - { - BridgeSettingSet("Theme", "Selected", QString("Default").toUtf8().constData()); - } - } - else - { - BridgeSettingSet("Theme", "Selected", QString("Default").toUtf8().constData()); + BridgeSettingSet("Theme", "Selected", appsUseLightTheme ? "Default" : "Dark"); + BridgeSettingSetUint("Theme", "AppsUseLightTheme", appsUseLightTheme); } } + + char selectedTheme[MAX_SETTING_SIZE] = "Default"; + if(!BridgeSettingGet("Theme", "Selected", selectedTheme)) + BridgeSettingSet("Theme", "Selected", selectedTheme); + + QString stylePath(":/css/default.css"); + QString settingsPath; if(*selectedTheme) { + QIcon::setThemeName(selectedTheme); + QString themePath = QString("%1/../themes/%2/style.css").arg(QCoreApplication::applicationDirPath()).arg(selectedTheme); if(QFile(themePath).exists()) stylePath = themePath; - QString settingsPath = QString("%1/../themes/%2/style.ini").arg(QCoreApplication::applicationDirPath()).arg(selectedTheme); - if(QFile(themePath).exists()) - styleSettings = settingsPath; - QIcon::setThemeName(selectedTheme); + + auto tryIni = [&settingsPath, &selectedTheme](const char* name) + { + if(!settingsPath.isEmpty()) + return; + QString iniPath = QString("%1/../themes/%2/%3").arg(QCoreApplication::applicationDirPath(), selectedTheme, name); + if(QFile(iniPath).exists()) + settingsPath = iniPath; + }; + tryIni("style.ini"); + tryIni("colors.ini"); } else { + // This code path should never be executed QIcon::setThemeName("Default"); } - QFile f(stylePath); - if(f.open(QFile::ReadOnly | QFile::Text)) + + QFile cssFile(stylePath); + if(cssFile.open(QFile::ReadOnly | QFile::Text)) { - QTextStream in(&f); - auto style = in.readAll(); - f.close(); + auto style = QTextStream(&cssFile).readAll(); + cssFile.close(); style = style.replace("url(./", QString("url(../themes/%2/").arg(selectedTheme)); qApp->setStyleSheet(style); } - if(!reloadStyleCss && !styleSettings.isEmpty()) - importSettings(styleSettings, { "Colors", "Fonts" }); + + // Skip changing the settings when only reloading the CSS + if(reloadOnlyStyleCss) + return; + + if(!settingsPath.isEmpty()) + { + // TODO: add an 'inherit' option to style.ini to inherit from another theme + importSettings(settingsPath, { "Colors", "Fonts" }); + } + else + { + // Reset [Colors] to default + Config()->Colors = Config()->defaultColors; + Config()->writeColors(); + BridgeSettingSetUint("Colors", "DarkTitleBar", 0); + // Reset [Fonts] to default (TODO: https://github.com/x64dbg/x64dbg/issues/2422) + //Config()->Fonts = Config()->defaultFonts; + //Config()->writeFonts(); + // Remove custom colors + BridgeSettingSet("Colors", "CustomColorCount", nullptr); + } } void MainWindow::themeTriggeredSlot() @@ -563,7 +601,7 @@ void MainWindow::themeTriggeredSlot() int nameIdx = dir.lastIndexOf('/'); QString name = dir.mid(nameIdx + 1); BridgeSettingSet("Theme", "Selected", name.toUtf8().constData()); - loadSelectedStyle(); + loadSelectedTheme(); updateDarkTitleBar(this); } @@ -1158,10 +1196,8 @@ void MainWindow::updateWindowTitleSlot(QString filename) void MainWindow::updateDarkTitleBar(QWidget* widget) { - // https://www.vergiliusproject.com/kernels/x64/Windows%2010%20%7C%202016/2009%2020H2%20(October%202020%20Update)/_KUSER_SHARED_DATA - uint32_t NtBuildNumber = *(uint32_t*)(0x7FFE0000 + 0x260); - - if(NtBuildNumber == 0 /* pre Windows-10 */ || NtBuildNumber < 17763) + auto NtBuildNumber = BridgeGetNtBuildNumber(); + if(NtBuildNumber < 17763) return; duint darkTitleBar = 0; @@ -1948,7 +1984,7 @@ void MainWindow::on_actionFaq_triggered() void MainWindow::on_actionReloadStylesheet_triggered() { - loadSelectedStyle(true); + loadSelectedTheme(true); ensurePolished(); update(); } @@ -2418,19 +2454,10 @@ void MainWindow::on_actionCheckUpdates_triggered() void MainWindow::on_actionDefaultTheme_triggered() { - // Delete [Theme] Selected - BridgeSettingSet("Theme", "Selected", QString("Default").toUtf8().constData()); + // Revert to the Default theme + BridgeSettingSet("Theme", "Selected", "Default"); // Load style - loadSelectedStyle(); - // Reset [Colors] to default - Config()->Colors = Config()->defaultColors; - Config()->writeColors(); - BridgeSettingSetUint("Colors", "DarkTitleBar", 0); - // Reset [Fonts] to default - //Config()->Fonts = Config()->defaultFonts; - //Config()->writeFonts(); - // Remove custom colors - BridgeSettingSet("Colors", "CustomColorCount", nullptr); + loadSelectedTheme(); updateDarkTitleBar(this); } diff --git a/src/gui/Src/Gui/MainWindow.h b/src/gui/Src/Gui/MainWindow.h index fb948346..ea0ba1d6 100644 --- a/src/gui/Src/Gui/MainWindow.h +++ b/src/gui/Src/Gui/MainWindow.h @@ -54,7 +54,7 @@ public: void loadTabSavedOrder(); void clearTabWidget(); - static void loadSelectedStyle(bool reloadStyleCss = false); + static void loadSelectedTheme(bool reloadOnlyStyleCss = false); static void updateDarkTitleBar(QWidget* widget); public slots: diff --git a/src/gui/Src/main.cpp b/src/gui/Src/main.cpp index 930f23bf..b559a7f7 100644 --- a/src/gui/Src/main.cpp +++ b/src/gui/Src/main.cpp @@ -139,10 +139,7 @@ int main(int argc, char* argv[]) { handleHighDpiScaling(); MyApplication application(argc, argv); - // For unclear reasons it looks like the search path order is inverted. - // This might be specific to Qt 5.6 and only matters when you override the "Default" theme - QIcon::setThemeSearchPaths({ ":/", QCoreApplication::applicationDirPath() + "/../themes" }); - MainWindow::loadSelectedStyle(true); + #if QT_VERSION < QT_VERSION_CHECK(5,0,0) QAbstractEventDispatcher::instance(application.thread())->setEventFilter(MyApplication::globalEventFilter); #else @@ -184,6 +181,12 @@ int main(int argc, char* argv[]) appPalette.setColor(QPalette::Link, ConfigColor("LinkColor")); application.setPalette(appPalette); + // Load the selected style + // For unclear reasons it looks like the search path order is inverted. + // This might be specific to Qt 5.6 and only matters when you override the "Default" theme + QIcon::setThemeSearchPaths({ ":/", QCoreApplication::applicationDirPath() + "/../themes" }); + MainWindow::loadSelectedTheme(); + // Register custom data types qRegisterMetaType("dsint"); qRegisterMetaType("duint");