Skip to content

Commit

Permalink
FEAT(client): Implement tray icon highlighting
Browse files Browse the repository at this point in the history
Previously, only "window highlighting" was supported
by Mumble. However, when Mumble was minimized to tray,
there was no way to observe that highlighting.

As requested in mumble-voip#4584, this commit introduces highlighting
to the tray icon. When a highlight message is received, the
tray icon will flash the "information icon" every two seconds
until the MainWindow of Mumble receives focus again.

To enable this for a specific message type, the user needs to
check the "highlight" box in the "Messages" configuration dialog.

Fixes mumble-voip#4584
  • Loading branch information
Hartmnt committed Jun 14, 2024
1 parent eec9ed0 commit 77962f4
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 4 deletions.
3 changes: 3 additions & 0 deletions src/mumble/Log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include "VolumeAdjustment.h"
#include "Global.h"

#include "widgets/TrayIcon.h"

#include <QSignalBlocker>
#include <QtCore/QMutexLocker>
#include <QtGui/QImageWriter>
Expand Down Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions src/mumble/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
#include <QtWidgets/QToolTip>
#include <QtWidgets/QWhatsThis>

#include "widgets/EventFilters.h"
#include "widgets/SemanticSlider.h"
#include "widgets/TrayIcon.h"

Expand Down Expand Up @@ -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")))
Expand Down Expand Up @@ -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);
}

Expand Down
1 change: 1 addition & 0 deletions src/mumble/MainWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
57 changes: 53 additions & 4 deletions src/mumble/widgets/TrayIcon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,16 @@
#include <QApplication>
#include <QDebug>

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)
Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
}
}
9 changes: 9 additions & 0 deletions src/mumble/widgets/TrayIcon.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

#include "../../QtUtils.h"
#include <QAction>
#include <QReadWriteLock>
#include <QTimer>
#include <QtWidgets/QMenu>
#include <QtWidgets/QSystemTrayIcon>

Expand All @@ -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_

0 comments on commit 77962f4

Please sign in to comment.