diff --git a/src/mumble/CMakeLists.txt b/src/mumble/CMakeLists.txt index fa41283bcca..aef67ab2ef8 100644 --- a/src/mumble/CMakeLists.txt +++ b/src/mumble/CMakeLists.txt @@ -309,6 +309,8 @@ set(MUMBLE_SOURCES "widgets/SearchDialogTree.h" "widgets/SemanticSlider.cpp" "widgets/SemanticSlider.h" + "widgets/TrayIcon.cpp" + "widgets/TrayIcon.h" "${SHARED_SOURCE_DIR}/ACL.cpp" diff --git a/src/mumble/Global.cpp b/src/mumble/Global.cpp index 06cab015838..de46978b0fd 100644 --- a/src/mumble/Global.cpp +++ b/src/mumble/Global.cpp @@ -93,6 +93,7 @@ void Global::migrateDataDir(const QDir &toDir) { Global::Global(const QString &qsConfigPath) { mw = 0; + trayIcon = 0; db = 0; pluginManager = 0; nam = 0; diff --git a/src/mumble/Global.h b/src/mumble/Global.h index c129d26e214..3f624e67fa4 100644 --- a/src/mumble/Global.h +++ b/src/mumble/Global.h @@ -34,6 +34,7 @@ class OverlayClient; class LogEmitter; class DeveloperConsole; class TalkingUI; +class TrayIcon; class QNetworkAccessManager; @@ -50,6 +51,7 @@ struct Global Q_DECL_FINAL { static Global &get(); MainWindow *mw; + TrayIcon *trayIcon; Settings s; boost::shared_ptr< ServerHandler > sh; boost::shared_ptr< AudioInput > ai; diff --git a/src/mumble/Log_unix.cpp b/src/mumble/Log_unix.cpp index 7e9159dcbab..c6006edef34 100644 --- a/src/mumble/Log_unix.cpp +++ b/src/mumble/Log_unix.cpp @@ -1,14 +1,25 @@ -// Copyright 2012-2023 The Mumble Developers. All rights reserved. +// Copyright 2012-2024 The Mumble Developers. All rights reserved. // Use of this source code is governed by a BSD-style license // that can be found in the LICENSE file at the root of the // Mumble source tree or at . #include "Log.h" -#include "MainWindow.h" -#include "Settings.h" - -#include +#include "Global.h" +#include "widgets/TrayIcon.h" void Log::postNotification(MsgType mt, const QString &plain) { - // FIXME + QSystemTrayIcon::MessageIcon msgIcon; + switch (mt) { + case DebugInfo: + case CriticalError: + msgIcon = QSystemTrayIcon::Critical; + break; + case Warning: + msgIcon = QSystemTrayIcon::Warning; + break; + default: + msgIcon = QSystemTrayIcon::Information; + break; + } + Global::get().trayIcon->showMessage(msgName(mt), plain, msgIcon); } diff --git a/src/mumble/Log_win.cpp b/src/mumble/Log_win.cpp index 04384099f0f..c6006edef34 100644 --- a/src/mumble/Log_win.cpp +++ b/src/mumble/Log_win.cpp @@ -1,10 +1,25 @@ -// Copyright 2012-2023 The Mumble Developers. All rights reserved. +// Copyright 2012-2024 The Mumble Developers. All rights reserved. // Use of this source code is governed by a BSD-style license // that can be found in the LICENSE file at the root of the // Mumble source tree or at . #include "Log.h" +#include "Global.h" +#include "widgets/TrayIcon.h" void Log::postNotification(MsgType mt, const QString &plain) { - // FIXME + QSystemTrayIcon::MessageIcon msgIcon; + switch (mt) { + case DebugInfo: + case CriticalError: + msgIcon = QSystemTrayIcon::Critical; + break; + case Warning: + msgIcon = QSystemTrayIcon::Warning; + break; + default: + msgIcon = QSystemTrayIcon::Information; + break; + } + Global::get().trayIcon->showMessage(msgName(mt), plain, msgIcon); } diff --git a/src/mumble/MainWindow.cpp b/src/mumble/MainWindow.cpp index b4e46f3f5f2..ad9fff9dc49 100644 --- a/src/mumble/MainWindow.cpp +++ b/src/mumble/MainWindow.cpp @@ -82,6 +82,7 @@ #include #include "widgets/SemanticSlider.h" +#include "widgets/TrayIcon.h" #ifdef Q_OS_WIN # include @@ -2536,6 +2537,8 @@ void MainWindow::updateMenuPermissions() { } void MainWindow::userStateChanged() { + Global::get().trayIcon->updateIcon(); + ClientUser *user = ClientUser::get(Global::get().uiSession); if (!user) { Global::get().bAttenuateOthers = false; diff --git a/src/mumble/main.cpp b/src/mumble/main.cpp index be28b37cf8e..241550fd297 100644 --- a/src/mumble/main.cpp +++ b/src/mumble/main.cpp @@ -51,6 +51,8 @@ #include "VersionCheck.h" #include "Global.h" +#include "widgets/TrayIcon.h" + #include #include #include @@ -684,6 +686,8 @@ int main(int argc, char **argv) { Global::get().mw = new MainWindow(nullptr); Global::get().mw->show(); + Global::get().trayIcon = new TrayIcon(Global::get().mw); + Global::get().talkingUI = new TalkingUI(); // Set TalkingUI's position diff --git a/src/mumble/widgets/TrayIcon.cpp b/src/mumble/widgets/TrayIcon.cpp new file mode 100644 index 00000000000..9a9d09e0c1b --- /dev/null +++ b/src/mumble/widgets/TrayIcon.cpp @@ -0,0 +1,75 @@ +// Copyright 2024 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +#include "TrayIcon.h" + +#include "../ClientUser.h" +#include "../Global.h" +#include "../MainWindow.h" + +#include + +TrayIcon::TrayIcon(QObject *parent) : QSystemTrayIcon(parent), m_statusIcon(nullptr) { + setIcon(Global::get().mw->qiIcon); + setToolTip("Mumble"); + show(); +} + +void TrayIcon::updateIcon() { + QIcon *newIcon = nullptr; + + ClientUser *p = ClientUser::get(Global::get().uiSession); + + if (Global::get().s.bDeaf) { + newIcon = &Global::get().mw->qiIconDeafSelf; + } else if (p && p->bDeaf) { + newIcon = &Global::get().mw->qiIconDeafServer; + } else if (Global::get().s.bMute) { + newIcon = &Global::get().mw->qiIconMuteSelf; + } else if (p && p->bMute) { + newIcon = &Global::get().mw->qiIconMuteServer; + } else if (p && p->bSuppress) { + newIcon = &Global::get().mw->qiIconMuteSuppressed; + } else if (Global::get().s.bStateInTray && Global::get().bPushToMute) { + newIcon = &Global::get().mw->qiIconMutePushToMute; + } else if (p && Global::get().s.bStateInTray) { + switch (p->tsState) { + case Settings::Talking: + case Settings::MutedTalking: + newIcon = &Global::get().mw->qiTalkingOn; + break; + case Settings::Whispering: + newIcon = &Global::get().mw->qiTalkingWhisper; + break; + case Settings::Shouting: + newIcon = &Global::get().mw->qiTalkingShout; + break; + case Settings::Passive: + default: + newIcon = &Global::get().mw->qiTalkingOff; + break; + } + } else { + newIcon = &Global::get().mw->qiIcon; + } + + if (newIcon != m_statusIcon) { + m_statusIcon = newIcon; + setIcon(*m_statusIcon); + } +} + +void TrayIcon::on_icon_clicked(QSystemTrayIcon::ActivationReason reason) { + qDebug() << reason; + switch (reason) { + case QSystemTrayIcon::Unknown: + case QSystemTrayIcon::Context: + case QSystemTrayIcon::DoubleClick: + case QSystemTrayIcon::Trigger: + case QSystemTrayIcon::MiddleClick: + default: + break; + } +} diff --git a/src/mumble/widgets/TrayIcon.h b/src/mumble/widgets/TrayIcon.h new file mode 100644 index 00000000000..ba45d805c19 --- /dev/null +++ b/src/mumble/widgets/TrayIcon.h @@ -0,0 +1,25 @@ +// Copyright 2024 The Mumble Developers. All rights reserved. +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file at the root of the +// Mumble source tree or at . + +#ifndef MUMBLE_MUMBLE_WIDGETS_TRAYICCON_H_ +#define MUMBLE_MUMBLE_WIDGETS_TRAYICCON_H_ + +#include + +class TrayIcon : public QSystemTrayIcon { + Q_OBJECT + +public: + TrayIcon(QObject *parent); + + void updateIcon(); + +private: + QIcon *m_statusIcon; + + void on_icon_clicked(QSystemTrayIcon::ActivationReason reason); +}; + +#endif // MUMBLE_MUMBLE_WIDGETS_TRAYICCON_H_