diff --git a/src/mumble/Log.cpp b/src/mumble/Log.cpp index ff0896fb4ce..740467574da 100644 --- a/src/mumble/Log.cpp +++ b/src/mumble/Log.cpp @@ -22,6 +22,8 @@ #include "VolumeAdjustment.h" #include "Global.h" +#include "widgets/TrayIcon.h" + #include #include #include @@ -804,6 +806,7 @@ void Log::log(MsgType mt, const QString &console, const QString &terse, bool own // Message notification with window highlight if (flags & Settings::LogHighlight) { QApplication::alert(Global::get().mw); + Global::get().trayIcon->on_highlight(); } // Message notification with balloon tooltips diff --git a/src/mumble/MainWindow.cpp b/src/mumble/MainWindow.cpp index 14a47e1efda..865fb8b45e9 100644 --- a/src/mumble/MainWindow.cpp +++ b/src/mumble/MainWindow.cpp @@ -81,6 +81,7 @@ #include #include +#include "widgets/EventFilters.h" #include "widgets/SemanticSlider.h" #include "widgets/TrayIcon.h" @@ -112,6 +113,7 @@ MainWindow::MainWindow(QWidget *p) SvgIcon::addSvgPixmapsToIcon(qiTalkingOn, QLatin1String("skin:talking_on.svg")); SvgIcon::addSvgPixmapsToIcon(qiTalkingShout, QLatin1String("skin:talking_alt.svg")); SvgIcon::addSvgPixmapsToIcon(qiTalkingWhisper, QLatin1String("skin:talking_whisper.svg")); + SvgIcon::addSvgPixmapsToIcon(iconInformation, QLatin1String("skin:Information_icon.svg")); #ifdef Q_OS_MAC if (QFile::exists(QLatin1String("skin:mumble.icns"))) @@ -724,6 +726,14 @@ void MainWindow::changeEvent(QEvent *e) { } } + // Unhighlight the tray icon when receiving focus + if (e->type() == QEvent::ActivationChange) { + if (isActiveWindow()) { + emit Global::get().trayIcon->on_unhighlight(); + } + return; + } + QWidget::changeEvent(e); } diff --git a/src/mumble/MainWindow.h b/src/mumble/MainWindow.h index 9c6c3d5ccaf..df0604609ef 100644 --- a/src/mumble/MainWindow.h +++ b/src/mumble/MainWindow.h @@ -80,6 +80,7 @@ class MainWindow : public QMainWindow, public Ui::MainWindow { QIcon qiIcon, qiIconMutePushToMute, qiIconMuteSelf, qiIconMuteServer, qiIconDeafSelf, qiIconDeafServer, qiIconMuteSuppressed; QIcon qiTalkingOn, qiTalkingWhisper, qiTalkingShout, qiTalkingOff; + QIcon iconInformation; std::unordered_map< unsigned int, qt_unique_ptr< UserLocalNicknameDialog > > qmUserNicknameTracker; /// "Action" for when there are no actions available diff --git a/src/mumble/widgets/TrayIcon.cpp b/src/mumble/widgets/TrayIcon.cpp index c17f5021161..b3e036f7114 100644 --- a/src/mumble/widgets/TrayIcon.cpp +++ b/src/mumble/widgets/TrayIcon.cpp @@ -12,10 +12,16 @@ #include #include -TrayIcon::TrayIcon() : QSystemTrayIcon(Global::get().mw), m_statusIcon(nullptr) { - setIcon(Global::get().mw->qiIcon); +TrayIcon::TrayIcon() + : QSystemTrayIcon(Global::get().mw), m_statusIcon(&Global::get().mw->qiIcon), m_currentIcon(nullptr), + m_iconLock(QReadWriteLock::NonRecursive) { + applyIcon(m_statusIcon); setToolTip("Mumble"); + m_highlightTimer = new QTimer(this); + m_highlightTimer->setSingleShot(true); + QObject::connect(m_highlightTimer, &QTimer::timeout, this, &TrayIcon::on_timer_triggered); + QObject::connect(this, &QSystemTrayIcon::activated, this, &TrayIcon::on_icon_clicked); // messageClicked is buggy in Qt on some platforms and we can not do anything about this (QTBUG-87329) @@ -76,9 +82,16 @@ void TrayIcon::updateIcon() { newIcon = &Global::get().mw->qiIcon; } - if (newIcon != m_statusIcon) { + m_iconLock.lockForRead(); + bool isStatusIcon = newIcon == m_statusIcon; + m_iconLock.unlock(); + + if (!isStatusIcon) { + m_iconLock.lockForWrite(); m_statusIcon = newIcon; - setIcon(*m_statusIcon); + m_iconLock.unlock(); + + applyIcon(m_statusIcon); } } @@ -116,6 +129,13 @@ void TrayIcon::updateContextMenu() { m_contextMenu->addAction(Global::get().mw->qaQuit); } +void TrayIcon::applyIcon(QIcon *icon) { + QWriteLocker locker(&m_iconLock); + + setIcon(*icon); + m_currentIcon = icon; +} + void TrayIcon::toggleShowHide() { if (Global::get().mw->isVisible() && !Global::get().mw->isMinimized()) { on_hideAction_triggered(); @@ -151,3 +171,32 @@ void TrayIcon::on_hideAction_triggered() { Global::get().mw->hide(); updateContextMenu(); } + +void TrayIcon::on_highlight() { + qDebug() << "Tray: Highlight notification received!"; + on_timer_triggered(); +} + +void TrayIcon::on_unhighlight() { + if (!m_highlightTimer->isActive()) { + return; + } + + qDebug() << "Tray: Unhighlight..."; + m_highlightTimer->stop(); + applyIcon(m_statusIcon); +} + +void TrayIcon::on_timer_triggered() { + m_iconLock.lockForRead(); + bool isStatusIcon = m_currentIcon == m_statusIcon; + m_iconLock.unlock(); + + if (isStatusIcon) { + applyIcon(&Global::get().mw->iconInformation); + m_highlightTimer->start(500); + } else { + applyIcon(m_statusIcon); + m_highlightTimer->start(2000); + } +} diff --git a/src/mumble/widgets/TrayIcon.h b/src/mumble/widgets/TrayIcon.h index d15d59693dd..51f8a8fc642 100644 --- a/src/mumble/widgets/TrayIcon.h +++ b/src/mumble/widgets/TrayIcon.h @@ -8,6 +8,8 @@ #include "../../QtUtils.h" #include +#include +#include #include #include @@ -23,17 +25,24 @@ class TrayIcon : public QSystemTrayIcon { public slots: void on_showAction_triggered(); void on_hideAction_triggered(); + void on_highlight(); + void on_unhighlight(); private: QIcon *m_statusIcon; + QIcon *m_currentIcon; QMenu *m_contextMenu; QAction *m_showAction; QAction *m_hideAction; + QTimer *m_highlightTimer; + QReadWriteLock m_iconLock; void updateContextMenu(); + void applyIcon(QIcon *icon); private slots: void on_icon_clicked(QSystemTrayIcon::ActivationReason reason); + void on_timer_triggered(); }; #endif // MUMBLE_MUMBLE_WIDGETS_TRAYICCON_H_