diff --git a/.env.example b/.env.example index 2122779da..99db1f1e6 100644 --- a/.env.example +++ b/.env.example @@ -9,6 +9,9 @@ # Serial key value to pre-fill the activation dialog # SYNERGY_TEST_SERIAL_KEY="DEADBEEF" +# Shows the test menu in the GUI (on by default in debug mode) +# SYNERGY_TEST_MENU=true + # Version checker URL to use (useful for testing) # SYNERGY_VERSION_URL="http://localhost:8787?version=v1" diff --git a/ChangeLog b/ChangeLog index 9d65411a8..882ad9b0b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -76,6 +76,7 @@ Enhancements: - #7430 Improve setting enable logic and test coverage - #7431 Improve handling of Qt-related warnings and errors - #7432 Only show close to tray reminder when not quitting the app +- #7434 Show dark logo in dark mode and improve .env loader # 1.14.6 diff --git a/src/gui/res/Synergy.qrc b/src/gui/res/Synergy.qrc index 230016546..e7bb40f31 100644 --- a/src/gui/res/Synergy.qrc +++ b/src/gui/res/Synergy.qrc @@ -1,25 +1,17 @@ - icons/16x16/synergy-connected.png - icons/16x16/synergy-disconnected.png + icons/16x16/synergy.png icons/64x64/video-display.png icons/64x64/user-trash.png icons/16x16/warning.png icons/256x256/synergy.ico - image/about.png + image/about-light.png image/about-dark.png - image/spinning-wheel.gif icons/16x16/padlock.png - icons/16x16/synergy-transfering.png - icons/64x64/synergy-dark-transfering.png - icons/64x64/synergy-dark-disconnected.png - icons/64x64/synergy-dark-connected.png - icons/64x64/synergy-light-transfering.png - icons/64x64/synergy-light-disconnected.png - icons/64x64/synergy-light-connected.png + icons/64x64/synergy-dark.png + icons/64x64/synergy-light.png image/welcome.png icons/64x64/folder.png - fonts/Arial.ttf - image/setupBlocker.png + image/setup-blocker.png diff --git a/src/gui/res/fonts/Arial.ttf b/src/gui/res/fonts/Arial.ttf deleted file mode 100644 index ff0815cd8..000000000 Binary files a/src/gui/res/fonts/Arial.ttf and /dev/null differ diff --git a/src/gui/res/icons/16x16/synergy-disconnected.png b/src/gui/res/icons/16x16/synergy-disconnected.png deleted file mode 100644 index 43d34e628..000000000 Binary files a/src/gui/res/icons/16x16/synergy-disconnected.png and /dev/null differ diff --git a/src/gui/res/icons/16x16/synergy-transfering.png b/src/gui/res/icons/16x16/synergy-transfering.png deleted file mode 100644 index 43d34e628..000000000 Binary files a/src/gui/res/icons/16x16/synergy-transfering.png and /dev/null differ diff --git a/src/gui/res/icons/16x16/synergy-connected.png b/src/gui/res/icons/16x16/synergy.png similarity index 100% rename from src/gui/res/icons/16x16/synergy-connected.png rename to src/gui/res/icons/16x16/synergy.png diff --git a/src/gui/res/icons/64x64/synergy-dark-disconnected.png b/src/gui/res/icons/64x64/synergy-dark-disconnected.png deleted file mode 100644 index e02e133ad..000000000 Binary files a/src/gui/res/icons/64x64/synergy-dark-disconnected.png and /dev/null differ diff --git a/src/gui/res/icons/64x64/synergy-dark-transfering.png b/src/gui/res/icons/64x64/synergy-dark-transfering.png deleted file mode 100644 index e02e133ad..000000000 Binary files a/src/gui/res/icons/64x64/synergy-dark-transfering.png and /dev/null differ diff --git a/src/gui/res/icons/64x64/synergy-dark-connected.png b/src/gui/res/icons/64x64/synergy-dark.png similarity index 100% rename from src/gui/res/icons/64x64/synergy-dark-connected.png rename to src/gui/res/icons/64x64/synergy-dark.png diff --git a/src/gui/res/icons/64x64/synergy-light-disconnected.png b/src/gui/res/icons/64x64/synergy-light-disconnected.png deleted file mode 100644 index 8a31d2590..000000000 Binary files a/src/gui/res/icons/64x64/synergy-light-disconnected.png and /dev/null differ diff --git a/src/gui/res/icons/64x64/synergy-light-transfering.png b/src/gui/res/icons/64x64/synergy-light-transfering.png deleted file mode 100644 index 8a31d2590..000000000 Binary files a/src/gui/res/icons/64x64/synergy-light-transfering.png and /dev/null differ diff --git a/src/gui/res/icons/64x64/synergy-light-connected.png b/src/gui/res/icons/64x64/synergy-light.png similarity index 100% rename from src/gui/res/icons/64x64/synergy-light-connected.png rename to src/gui/res/icons/64x64/synergy-light.png diff --git a/src/gui/res/image/about.png b/src/gui/res/image/about-light.png similarity index 100% rename from src/gui/res/image/about.png rename to src/gui/res/image/about-light.png diff --git a/src/gui/res/image/setupBlocker.png b/src/gui/res/image/setup-blocker.png similarity index 100% rename from src/gui/res/image/setupBlocker.png rename to src/gui/res/image/setup-blocker.png diff --git a/src/gui/res/image/spinning-wheel.gif b/src/gui/res/image/spinning-wheel.gif deleted file mode 100644 index 220f02071..000000000 Binary files a/src/gui/res/image/spinning-wheel.gif and /dev/null differ diff --git a/src/gui/src/AboutDialog.cpp b/src/gui/src/AboutDialog.cpp index bc3c727f6..4ded04aae 100644 --- a/src/gui/src/AboutDialog.cpp +++ b/src/gui/src/AboutDialog.cpp @@ -17,15 +17,15 @@ */ #include "AboutDialog.h" + #include "common/copyright.h" +#include "common/version.h" +#include "gui/style_utils.h" #include +#include -#if defined(Q_OS_MAC) -#include "gui/OSXHelpers.h" -#endif - -#include "common/version.h" +using namespace synergy::gui; AboutDialog::AboutDialog(MainWindow *parent) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint), @@ -53,14 +53,15 @@ int AboutDialog::exec() { } void AboutDialog::updateLogo() const { -#if defined(Q_OS_MAC) - if (isOSXInterfaceStyleDark()) { + if (isDarkMode()) { + qDebug("dark mode detected, showing dark logo"); QPixmap logo(":/res/image/about-dark.png"); if (!logo.isNull()) { m_pLabel_Logo->setPixmap(logo); } + } else { + qDebug("light mode detected, keeping light logo"); } -#endif } QString AboutDialog::importantDevelopers() const { diff --git a/src/gui/src/MainWindow.cpp b/src/gui/src/MainWindow.cpp index 96e469df0..b8a7a4d80 100644 --- a/src/gui/src/MainWindow.cpp +++ b/src/gui/src/MainWindow.cpp @@ -65,30 +65,12 @@ using CoreMode = CoreProcess::Mode; using CoreConnectionState = CoreProcess::ConnectionState; using CoreProcessState = CoreProcess::ProcessState; -#if defined(Q_OS_MAC) +const auto kIconFile16 = ":/res/icons/16x16/synergy.png"; -static const char *const kLightIconFiles[] = { - ":/res/icons/64x64/synergy-light-disconnected.png", - ":/res/icons/64x64/synergy-light-disconnected.png", - ":/res/icons/64x64/synergy-light-connected.png", - ":/res/icons/64x64/synergy-light-transfering.png", - ":/res/icons/64x64/synergy-light-disconnected.png"}; - -static const char *const kDarkIconFiles[] = { - ":/res/icons/64x64/synergy-dark-disconnected.png", - ":/res/icons/64x64/synergy-dark-disconnected.png", - ":/res/icons/64x64/synergy-dark-connected.png", - ":/res/icons/64x64/synergy-dark-transfering.png", - ":/res/icons/64x64/synergy-dark-disconnected.png"}; - -#endif - -static const char *const kDefaultIconFiles[] = { - ":/res/icons/16x16/synergy-disconnected.png", - ":/res/icons/16x16/synergy-disconnected.png", - ":/res/icons/16x16/synergy-connected.png", - ":/res/icons/16x16/synergy-transfering.png", - ":/res/icons/16x16/synergy-disconnected.png"}; +#ifdef Q_OS_MAC +const auto kLightIconFile = ":/res/icons/64x64/synergy-light.png"; +const auto kDarkIconFile = ":/res/icons/64x64/synergy-dark.png"; +#endif // Q_OS_MAC MainWindow::MainWindow(ConfigScopes &configScopes, AppConfig &appConfig) : m_ConfigScopes(configScopes), @@ -164,6 +146,7 @@ void MainWindow::setupControls() { createMenuBar(); secureSocket(false); + updateLocalFingerprint(); m_pLabelUpdate->setStyleSheet(kStyleNoticeLabel); m_pLabelUpdate->hide(); @@ -262,7 +245,7 @@ void MainWindow::connectSlots() { connect(m_pActionQuit, &QAction::triggered, qApp, [this] { qDebug("quitting application"); m_Quitting = true; - qApp->quit(); + QApplication::quit(); }); connect( @@ -294,7 +277,7 @@ void MainWindow::onAppAboutToQuit() { m_ConfigScopes.save(); } void MainWindow::onCreated() { - setIcon(CoreConnectionState::Disconnected); + setIcon(); m_ConfigScopes.signalReady(); @@ -655,26 +638,24 @@ void MainWindow::saveSettings() { m_ConfigScopes.save(); } -void MainWindow::setIcon(CoreConnectionState state) { +void MainWindow::setIcon() { QIcon icon; - auto index = static_cast(state); - #ifdef Q_OS_MAC switch (getOSXIconsTheme()) { case IconsTheme::ICONS_DARK: - icon.addFile(kDarkIconFiles[index]); + icon.addFile(kDarkIconFile); break; case IconsTheme::ICONS_LIGHT: - icon.addFile(kLightIconFiles[index]); + icon.addFile(kLightIconFile); break; case IconsTheme::ICONS_TEMPLATE: default: - icon.addFile(kDarkIconFiles[index]); + icon.addFile(kDarkIconFile); icon.setIsMask(true); break; } #else - icon.addFile(kDefaultIconFiles[index]); + icon.addFile(kIconFile16); #endif m_TrayIcon.setIcon(icon); @@ -840,23 +821,18 @@ void MainWindow::updateStatus() { using enum CoreProcessState; case Starting: - setIcon(CoreConnectionState::Disconnected); setStatus("Synergy is starting..."); break; case Stopping: - setIcon(CoreConnectionState::Disconnected); setStatus("Synergy is stopping..."); break; case Stopped: - setIcon(CoreConnectionState::Disconnected); setStatus("Synergy is not running"); break; case Started: { - setIcon(connection); - switch (connection) { using enum CoreConnectionState; diff --git a/src/gui/src/MainWindow.h b/src/gui/src/MainWindow.h index f6b492b27..6e396f710 100644 --- a/src/gui/src/MainWindow.h +++ b/src/gui/src/MainWindow.h @@ -143,7 +143,7 @@ private: void createTrayIcon(); void applyConfig(); void applyCloseToTray() const; - void setIcon(CoreProcess::ConnectionState state); + void setIcon(); bool checkForApp(int which, QString &app); void setStatus(const QString &status); void sendIpcMessage(IpcMessageType type, const char *buffer, bool showErrors); diff --git a/src/lib/gui/config/AppConfig.cpp b/src/lib/gui/config/AppConfig.cpp index 7130ba5d4..ae7046407 100644 --- a/src/lib/gui/config/AppConfig.cpp +++ b/src/lib/gui/config/AppConfig.cpp @@ -258,7 +258,11 @@ void AppConfig::determineScope() { settingName(Setting::kLoadSystemSettings), m_LoadFromSystemScope, ConfigScopes::Scope::User) .toBool(); - + if (loadFromSystemScope) { + qDebug("user settings indicates system scope should be used"); + } else { + qDebug("user settings indicates user scope should be used"); + } setLoadFromSystemScope(loadFromSystemScope); } @@ -268,6 +272,7 @@ void AppConfig::determineScope() { else if (m_Scopes.scopeContains( settingName(Setting::kScreenName), ConfigScopes::Scope::System)) { + qDebug("system settings scope contains screen name, using system scope"); setLoadFromSystemScope(true); } } @@ -409,10 +414,8 @@ void AppConfig::setLoadFromSystemScope(bool value) { using enum ConfigScopes::Scope; if (value) { - qDebug("loading system settings scope"); loadScope(System); } else { - qDebug("loading user settings scope"); loadScope(User); } diff --git a/src/lib/gui/core/CoreProcess.cpp b/src/lib/gui/core/CoreProcess.cpp index 723c8ba6e..4b8f2a0fa 100644 --- a/src/lib/gui/core/CoreProcess.cpp +++ b/src/lib/gui/core/CoreProcess.cpp @@ -520,7 +520,7 @@ bool CoreProcess::serverArgs(QStringList &args, QString &app) { args << "--address" << correctedInterface(); args << "-c" << configFilename; - qInfo("config file: %s", qPrintable(configFilename)); + qInfo("core config file: %s", qPrintable(configFilename)); if (kEnableActivation && !m_appConfig.serialKey().isEmpty()) { args << "--serial-key" << m_appConfig.serialKey(); @@ -585,7 +585,8 @@ QString CoreProcess::persistConfig() const { QFile configFile(configDirPath + "/" + kLastConfigFilename); if (!configFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { qWarning( - "failed to open config file: %s", qPrintable(configFile.fileName())); + "failed to open core config file: %s", + qPrintable(configFile.fileName())); continue; } diff --git a/src/lib/gui/dialogs/SettingsDialog.cpp b/src/lib/gui/dialogs/SettingsDialog.cpp index 8d1a03da5..1429b4ae2 100644 --- a/src/lib/gui/dialogs/SettingsDialog.cpp +++ b/src/lib/gui/dialogs/SettingsDialog.cpp @@ -90,6 +90,7 @@ void SettingsDialog::on_m_pCheckBoxEnableTls_clicked(bool) { if (kEnableActivation && !m_tlsUtility.isAvailable()) { m_pCheckBoxEnableTls->setChecked(false); + updateTlsControlsEnabled(); auto edition = m_license.productEdition(); if (edition == Edition::kBasic) { diff --git a/src/lib/gui/dotenv.cpp b/src/lib/gui/dotenv.cpp index be7b2ec11..c4d885ac8 100644 --- a/src/lib/gui/dotenv.cpp +++ b/src/lib/gui/dotenv.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -54,15 +55,23 @@ void dotenv(const QString &filename) { "no %s file in dir: %s", qPrintable(filename), qPrintable(fileInfo.absolutePath())); - // if nothing in current dir, then try app dir. this makes it a bit easier - // for engineers in the field to have an easily predictable location for the - // .env file. - QDir dir(QCoreApplication::applicationDirPath()); - filePath = dir.filePath(filename); + // if nothing in current dir, then try the app data dir. + // this makes it a bit easier for engineers in the field to have an easily + // predictable location for the .env file. + QDir configDir( + QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation)); + + // HACK: since we have the org name set to the app name, the config dir is + // confusing. make this simple by using the org dir instead. + // use `filePath("..")` instead of `cdUp` to avoid the existence check. + QDir orgDir = configDir.filePath(".."); + orgDir = orgDir.absolutePath(); + + filePath = orgDir.filePath(filename); if (!open(file, filePath)) { qInfo( - "no %s file in app dir: %s", qPrintable(filename), - qPrintable(dir.absolutePath())); + "no %s file in app config dir: %s", qPrintable(filename), + qPrintable(orgDir.absolutePath())); return; } } diff --git a/src/lib/gui/style_utils.h b/src/lib/gui/style_utils.h new file mode 100644 index 000000000..2c2b2441b --- /dev/null +++ b/src/lib/gui/style_utils.h @@ -0,0 +1,42 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2024 Symless + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file LICENSE that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include +#include +#include + +namespace synergy::gui { + +/** + * @brief Detects dark mode depending on Qt version. + * https://www.qt.io/blog/dark-mode-on-windows-11-with-qt-6.5 + */ +inline bool isDarkMode() { +#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) + const auto scheme = QGuiApplication::styleHints()->colorScheme(); + return scheme == Qt::ColorScheme::Dark; +#else + const QPalette defaultPalette; + const auto text = defaultPalette.color(QPalette::WindowText); + const auto window = defaultPalette.color(QPalette::Window); + return text.lightness() > window.lightness(); +#endif // QT_VERSION +} + +} // namespace synergy::gui