diff --git a/internal/frontend/bridge-gui/bridge-gui/TrayIcon.cpp b/internal/frontend/bridge-gui/bridge-gui/TrayIcon.cpp index 2a16c740..b389d89e 100644 --- a/internal/frontend/bridge-gui/bridge-gui/TrayIcon.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/TrayIcon.cpp @@ -33,6 +33,8 @@ QColor const errorColor(220, 50, 81); ///< The error state color. QColor const warnColor(255, 153, 0); ///< The warn state color. QColor const updateColor(35, 158, 206); ///< The warn state color. QColor const greyColor(112, 109, 107); ///< The grey color. +qint64 const iconRefreshTimerIntervalMs = 1000; ///< The interval for the refresh timer when switching DPI / screen config, in milliseconds. +qint64 const iconRefreshDurationSecs = 10; ///< The total number of seconds during wich we periodically refresh the icon after a DPI change. //**************************************************************************************************************************************************** @@ -112,6 +114,17 @@ TrayIcon::TrayIcon() this->show(); this->setState(State::Normal, QString(), QString()); + + // TrayIcon does not expose its screen, so we connect relevant screen events to our DPI change handler. + for (QScreen *screen: QGuiApplication::screens()) { + connect(screen, &QScreen::logicalDotsPerInchChanged, this, &TrayIcon::handleDPIChange); + } + connect(qApp, &QApplication::screenAdded, [&](QScreen *screen) { connect(screen, &QScreen::logicalDotsPerInchChanged, this, &TrayIcon::handleDPIChange); }); + connect(qApp, &QApplication::primaryScreenChanged, [&](QScreen *screen) { connect(screen, &QScreen::logicalDotsPerInchChanged, this, &TrayIcon::handleDPIChange); }); + + iconRefreshTimer_.setSingleShot(false); + iconRefreshTimer_.setInterval(iconRefreshTimerIntervalMs); + connect(&iconRefreshTimer_, &QTimer::timeout, this, &TrayIcon::onIconRefreshTimer); } @@ -155,6 +168,46 @@ void TrayIcon::onActivated(QSystemTrayIcon::ActivationReason reason) { } +//**************************************************************************************************************************************************** +// +//**************************************************************************************************************************************************** +void TrayIcon::handleDPIChange() { + this->setIcon(); + + // Windows forces us to apply a hack. Tray icon does not redraw by itself, so we use the Qt signal that detects screen and DPI changes. + // But the moment we get the signal the DPI change is not yet in effect. so redrawing now will have no effect, and we don't really + // know when we can safely redraw. So we will redraw the icon every second for some time. + iconRefreshDeadline_ = QDateTime::currentDateTime().addSecs(iconRefreshDurationSecs); + if (!iconRefreshTimer_.isActive()) { + iconRefreshTimer_.start(); + } +} + + +//**************************************************************************************************************************************************** +// +//**************************************************************************************************************************************************** +void TrayIcon::setIcon() { + QString const style = onMacOS() ? "mono" : "color"; + QString const text = stateText(state_); + + QIcon icon = loadIconFromImage(QString(":/qml/icons/systray-%1-%2.png").arg(style, text)); + icon.setIsMask(true); + QSystemTrayIcon::setIcon(icon); +} + + +//**************************************************************************************************************************************************** +// +//**************************************************************************************************************************************************** +void TrayIcon::onIconRefreshTimer() { + this->setIcon(); + if (QDateTime::currentDateTime() > iconRefreshDeadline_) { + iconRefreshTimer_.stop(); + } +} + + //**************************************************************************************************************************************************** // //**************************************************************************************************************************************************** @@ -184,14 +237,7 @@ void TrayIcon::generateDotIcons() { void TrayIcon::setState(TrayIcon::State state, QString const &stateString, QString const &statusIconPath) { stateString_ = stateString; state_ = state; - QString const style = onMacOS() ? "mono" : "color"; - QString const text = stateText(state); - - - QIcon icon = loadIconFromImage(QString(":/qml/icons/systray-%1-%2.png").arg(style, text)); - icon.setIsMask(true); - this->setIcon(icon); - + this->setIcon(); this->generateStatusIcon(statusIconPath, stateColor(state)); } diff --git a/internal/frontend/bridge-gui/bridge-gui/TrayIcon.h b/internal/frontend/bridge-gui/bridge-gui/TrayIcon.h index 8517ec8f..74cfdc94 100644 --- a/internal/frontend/bridge-gui/bridge-gui/TrayIcon.h +++ b/internal/frontend/bridge-gui/bridge-gui/TrayIcon.h @@ -41,6 +41,7 @@ public: // data members TrayIcon& operator=(TrayIcon const&) = delete; ///< Disabled assignment operator. TrayIcon& operator=(TrayIcon&&) = delete; ///< Disabled move assignment operator. void setState(State state, QString const& stateString, QString const &statusIconPath); ///< Set the state of the icon + void showNotificationPopup(QString const& title, QString const &message, QString const& iconPath); ///< Display a pop up notification. signals: void selectUser(QString const& userID); ///< Signal for selecting a user with a given userID @@ -49,6 +50,9 @@ private slots: void onMenuAboutToShow(); ///< Slot called before the context menu is shown. void onUserClicked(); ///< Slot triggered when clicking on a user in the context menu. static void onActivated(QSystemTrayIcon::ActivationReason reason); ///< Slot for the activation of the system tray icon. + void handleDPIChange(); ///< Handles DPI change. + void setIcon(); ///< set the tray icon. + void onIconRefreshTimer(); ///< Timer for icon refresh. private: // member functions. void generateDotIcons(); ///< generate the colored dot icons used for user status. @@ -63,6 +67,9 @@ private: // data members QIcon greenDot_; ///< The green dot icon. QIcon greyDot_; ///< The grey dot icon. QIcon orangeDot_; ///< The orange dot icon. + + QTimer iconRefreshTimer_; ///< The timer used to periodically refresh the icon when DPI changes. + QDateTime iconRefreshDeadline_; ///< The deadline for refreshing the icon };