fix(icon): use Qt tray icon in all cases, remove platform specific backends

qTox added specialized tray icon backends over time to work around bugs with
the default implementation, since then our GTK+2 backend has stopped working,
our appindicator backend was never selected by default by cmake, and
statusnotifier was never selected at SystemTrayIcon construction, leaving us
only ever using the broken GTK+2 backend, or theoretically the Unity backend,
which I didn't see selected on Ubuntu 16.04 Unity. In all other cases we would
fall back to the Qt backend.

Qt icon has improved over time, and our platform specific icons have become
stale, with GTK+2 becoming deprecated and GTK+3 not having a similar feature,
QSystemTrayIcon has been tested on a variety of DEs and works as well or better
in all cases, as shown in the table at
https://github.com/qTox/qTox/issues/5881#issuecomment-541892457

Fix #5881
Fix #5859
reviewable/pr5888/r2
Anthony Bilinski 2019-10-15 03:35:49 -07:00
parent 93c9eef51f
commit e85d3f522a
No known key found for this signature in database
GPG Key ID: 2AA8E0DA1B31FB3C
7 changed files with 3 additions and 567 deletions

View File

@ -526,9 +526,6 @@ set(${PROJECT_NAME}_SOURCES
src/widget/splitterrestorer.h
src/widget/style.cpp
src/widget/style.h
src/widget/systemtrayicon.cpp
src/widget/systemtrayicon.h
src/widget/systemtrayicon_private.h
src/widget/tool/activatedialog.cpp
src/widget/tool/activatedialog.h
src/widget/tool/adjustingscrollarea.cpp
@ -628,59 +625,12 @@ if (NOT DEFINED ENABLE_STATUSNOTIFIER AND UNIX AND NOT APPLE)
set(ENABLE_STATUSNOTIFIER True)
endif()
if(${ENABLE_STATUSNOTIFIER})
search_dependency(GDK_PIXBUF PACKAGE gdk-pixbuf-2.0 OPTIONAL)
search_dependency(GLIB PACKAGE glib-2.0 OPTIONAL)
search_dependency(GTK PACKAGE gtk+-2.0 OPTIONAL)
if(GDK_PIXBUF_FOUND AND GLIB_FOUND AND GTK_FOUND)
set(${PROJECT_NAME}_SOURCES ${${PROJECT_NAME}_SOURCES}
src/platform/statusnotifier/closures.c
src/platform/statusnotifier/closures.h
src/platform/statusnotifier/enums.c
src/platform/statusnotifier/enums.h
src/platform/statusnotifier/interfaces.h
src/platform/statusnotifier/statusnotifier.c
src/platform/statusnotifier/statusnotifier.h)
add_definitions(-DENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND=1)
endif()
endif()
if(AVFOUNDATION_FOUND)
set(${PROJECT_NAME}_SOURCES ${${PROJECT_NAME}_SOURCES}
src/platform/camera/avfoundation.mm
src/platform/camera/avfoundation.h)
endif()
if (NOT DEFINED ENABLE_APPINDICATOR AND UNIX AND NOT APPLE)
set(ENABLE_APPINDICATOR False)
endif()
if(${ENABLE_APPINDICATOR})
search_dependency(APPINDICATOR PACKAGE appindicator-0.1)
search_dependency(GDK_PIXBUF PACKAGE gdk-pixbuf-2.0)
search_dependency(GLIB PACKAGE glib-2.0)
search_dependency(GTK PACKAGE gtk+-2.0)
if(APPINDICATOR_FOUND)
add_definitions(-DENABLE_SYSTRAY_UNITY_BACKEND=1)
endif()
endif()
if (NOT DEFINED ENABLE_GTK_SYSTRAY AND UNIX AND NOT APPLE)
set(ENABLE_GTK_SYSTRAY True)
endif()
if(${ENABLE_GTK_SYSTRAY})
if(NOT GTK_FOUND)
search_dependency(GTK PACKAGE gtk+-2.0 OPTIONAL)
endif()
if(GTK_FOUND)
add_definitions(-DENABLE_SYSTRAY_GTK_BACKEND=1)
endif()
endif()
if(${USE_FILTERAUDIO})
search_dependency(FILTERAUDIO LIBRARY filteraudio HEADER filter_audio.h OPTIONAL)
if(${FILTERAUDIO_FOUND})

View File

@ -88,36 +88,6 @@ of spell check).
Disabled if dependencies are missing during compilation.
#### KDE Status Notifier / GTK tray backend
| Name | Version |
|-------------|---------|
| [Atk] | >= 2.14 |
| [Cairo] | |
| [GdkPixbuf] | >= 2.31 |
| [GLib] | >= 2.0 |
| [GTK+] | >= 2.0 |
| [Pango] | >= 1.18 |
To disable: `-DENABLE_STATUSNOTIFIER=False -DENABLE_GTK_SYSTRAY=False`
#### Unity tray backend
Disabled by default.
| Name | Version |
|-------------------|-----------|
| [Atk] | >= 2.14 |
| [Cairo] | |
| [DBus Menu] | >= 0.6 |
| [GdkPixbuf] | >= 2.31 |
| [GLib] | >= 2.0 |
| [GTK+] | >= 2.0 |
| [libappindicator] | >= 0.4.92 |
| [Pango] | >= 1.18 |
To enable: `-DENABLE_APPINDICATOR=True`
#### Snorenotify desktop notification backend
Disabled by default
@ -832,10 +802,6 @@ Switches:
[DBus Menu]: https://launchpad.net/libdbusmenu
[FFmpeg]: https://www.ffmpeg.org/
[GCC]: https://gcc.gnu.org/
[GdkPixbuf]: https://developer.gnome.org/gdk-pixbuf/
[GLib]: https://wiki.gnome.org/Projects/GLib
[GTK+]: https://www.gtk.org/
[libappindicator]: https://launchpad.net/libappindicator
[libX11]: https://www.x.org/wiki/
[libXScrnSaver]: https://www.x.org/wiki/Releases/ModuleVersions/
[MinGW]: http://www.mingw.org/

View File

@ -1,335 +0,0 @@
/*
Copyright © 2015-2019 by The qTox Project Contributors
This file is part of qTox, a Qt-based graphical interface for Tox.
qTox is libre software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
qTox 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 qTox. If not, see <http://www.gnu.org/licenses/>.
*/
#include "systemtrayicon.h"
#include "src/persistence/settings.h"
#include <QDebug>
#include <QFile>
#include <QMenu>
#include <QString>
#include <QSystemTrayIcon>
SystemTrayIcon::SystemTrayIcon()
{
QString desktop = getenv("XDG_CURRENT_DESKTOP");
if (desktop.isEmpty())
desktop = getenv("DESKTOP_SESSION");
desktop = desktop.toLower();
if (false)
;
#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
else if (desktop == "unity") {
qDebug() << "Using Unity backend";
gtk_init(nullptr, nullptr);
QString settingsDir = Settings::getInstance().getSettingsDirPath();
QFile iconFile(settingsDir + "/icon.png");
if (iconFile.open(QIODevice::Truncate | QIODevice::WriteOnly)) {
QFile resIconFile(":/img/icon.png");
if (resIconFile.open(QIODevice::ReadOnly))
iconFile.write(resIconFile.readAll());
resIconFile.close();
iconFile.close();
}
backendType = SystrayBackendType::Unity;
unityMenu = gtk_menu_new();
const std::string settingsDirString = settingsDir.toStdString();
unityIndicator =
app_indicator_new_with_path("qTox", "icon", APP_INDICATOR_CATEGORY_APPLICATION_STATUS,
settingsDirString.c_str());
app_indicator_set_menu(unityIndicator, GTK_MENU(unityMenu));
}
#endif
#ifdef ENABLE_SYSTRAY_GTK_BACKEND
else if (desktop == "xfce" || desktop.contains("gnome") || desktop == "mate"
|| desktop == "x-cinnamon") {
qDebug() << "Using GTK backend";
backendType = SystrayBackendType::GTK;
gtk_init(nullptr, nullptr);
gtkIcon = gtk_status_icon_new();
gtkMenu = gtk_menu_new();
void (*callbackTrigger)(GtkStatusIcon*, gpointer) = [](GtkStatusIcon*, gpointer data) {
static_cast<SystemTrayIcon*>(data)->activated(QSystemTrayIcon::Trigger);
};
g_signal_connect(gtkIcon, "activate", G_CALLBACK(callbackTrigger), this);
void (*callbackButtonClick)(GtkStatusIcon*, GdkEvent*,
gpointer) = [](GtkStatusIcon*, GdkEvent* event, gpointer data) {
if (event->button.button == 2)
static_cast<SystemTrayIcon*>(data)->activated(QSystemTrayIcon::MiddleClick);
};
g_signal_connect(gtkIcon, "button-release-event", G_CALLBACK(callbackButtonClick), this);
}
#endif
else {
qDebug() << "Using the Qt backend";
qtIcon = new QSystemTrayIcon;
backendType = SystrayBackendType::Qt;
connect(qtIcon, &QSystemTrayIcon::activated, this, &SystemTrayIcon::activated);
}
}
SystemTrayIcon::~SystemTrayIcon()
{
qDebug() << "Deleting SystemTrayIcon";
delete qtIcon;
}
QString SystemTrayIcon::extractIconToFile(QIcon icon, QString name)
{
QString iconPath;
(void)icon;
(void)name;
#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
iconPath = Settings::getInstance().getSettingsDirPath() + "/" + name + ".png";
QSize iconSize = icon.actualSize(QSize{64, 64});
icon.pixmap(iconSize).save(iconPath);
#endif
return iconPath;
}
#if defined(ENABLE_SYSTRAY_GTK_BACKEND) || defined(ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND)
GdkPixbuf* SystemTrayIcon::convertQIconToPixbuf(const QIcon& icon)
{
void (*callbackFreeImage)(guchar*, gpointer) = [](guchar* image_bytes, gpointer) {
delete[] image_bytes;
};
QImage image = icon.pixmap(64, 64).toImage();
if (image.format() != QImage::Format_RGBA8888_Premultiplied)
image = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
guchar* image_bytes = new guchar[image.sizeInBytes()];
memcpy(image_bytes, image.bits(), image.sizeInBytes());
#else
guchar* image_bytes = new guchar[image.byteCount()];
memcpy(image_bytes, image.bits(), image.byteCount());
#endif
return gdk_pixbuf_new_from_data(image_bytes, GDK_COLORSPACE_RGB, image.hasAlphaChannel(), 8,
image.width(), image.height(), image.bytesPerLine(),
callbackFreeImage, nullptr);
}
#endif
void SystemTrayIcon::setContextMenu(QMenu* menu)
{
if (false)
;
#ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND
else if (backendType == SystrayBackendType::StatusNotifier) {
void (*callbackClick)(StatusNotifier*, gint, gint, gpointer) = [](StatusNotifier*, gint,
gint, gpointer data) {
static_cast<SystemTrayIcon*>(data)->activated(QSystemTrayIcon::Trigger);
};
g_signal_connect(statusNotifier, "activate", G_CALLBACK(callbackClick), this);
void (*callbackMiddleClick)(StatusNotifier*, gint, gint,
gpointer) = [](StatusNotifier*, gint, gint, gpointer data) {
static_cast<SystemTrayIcon*>(data)->activated(QSystemTrayIcon::MiddleClick);
};
g_signal_connect(statusNotifier, "secondary_activate", G_CALLBACK(callbackMiddleClick), this);
for (QAction* a : menu->actions()) {
const std::string aText = a->text().replace('&', "").toStdString();
GtkWidget* item;
if (a->isSeparator())
item = gtk_menu_item_new();
else if (a->icon().isNull())
item = gtk_menu_item_new_with_label(aText.c_str());
else {
GdkPixbuf* pixbuf = convertQIconToPixbuf(a->icon());
item = gtk_image_menu_item_new_with_label(aText.c_str());
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
gtk_image_new_from_pixbuf(pixbuf));
gtk_image_menu_item_set_always_show_image(GTK_IMAGE_MENU_ITEM(item), TRUE);
g_object_unref(pixbuf);
}
gtk_menu_shell_append(GTK_MENU_SHELL(snMenu), item);
void (*callback)(GtkMenu*, gpointer data) = [](GtkMenu*, gpointer a) {
((QAction*)a)->activate(QAction::Trigger);
};
g_signal_connect(item, "activate", G_CALLBACK(callback), a);
gtk_widget_show(item);
}
void (*callbackMenu)(StatusNotifier*, gint, gint, gpointer) = [](StatusNotifier*, gint,
gint, gpointer data) {
gtk_widget_show_all(static_cast<SystemTrayIcon*>(data)->snMenu);
gtk_menu_popup(GTK_MENU(static_cast<SystemTrayIcon*>(data)->snMenu), 0, 0, 0, 0, 3,
gtk_get_current_event_time());
};
g_signal_connect(statusNotifier, "context-menu", G_CALLBACK(callbackMenu), this);
}
#endif
#ifdef ENABLE_SYSTRAY_GTK_BACKEND
else if (backendType == SystrayBackendType::GTK) {
for (QAction* a : menu->actions()) {
const std::string aText = a->text().replace('&', "").toStdString();
GtkWidget* item;
if (a->isSeparator())
item = gtk_menu_item_new();
else if (a->icon().isNull())
item = gtk_menu_item_new_with_label(aText.c_str());
else {
GdkPixbuf* pixbuf = convertQIconToPixbuf(a->icon());
item = gtk_image_menu_item_new_with_label(aText.c_str());
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
gtk_image_new_from_pixbuf(pixbuf));
gtk_image_menu_item_set_always_show_image(GTK_IMAGE_MENU_ITEM(item), TRUE);
g_object_unref(pixbuf);
}
gtk_menu_shell_append(GTK_MENU_SHELL(gtkMenu), item);
void (*callback)(GtkMenu*, gpointer data) = [](GtkMenu*, gpointer a) {
((QAction*)a)->activate(QAction::Trigger);
};
g_signal_connect(item, "activate", G_CALLBACK(callback), a);
gtk_widget_show(item);
}
void (*callbackMenu)(GtkMenu*, gint, gint, gpointer) = [](GtkMenu*, gint, gint, gpointer data) {
gtk_widget_show_all(static_cast<SystemTrayIcon*>(data)->gtkMenu);
gtk_menu_popup(GTK_MENU(static_cast<SystemTrayIcon*>(data)->gtkMenu), 0, 0, 0, 0, 3,
gtk_get_current_event_time());
};
g_signal_connect(gtkIcon, "popup-menu", G_CALLBACK(callbackMenu), this);
}
#endif
#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
else if (backendType == SystrayBackendType::Unity) {
for (QAction* a : menu->actions()) {
const std::string aText = a->text().replace('&', "").toStdString();
GtkWidget* item;
if (a->isSeparator())
item = gtk_menu_item_new();
else if (a->icon().isNull())
item = gtk_menu_item_new_with_label(aText.c_str());
else {
const std::string iconPath =
extractIconToFile(a->icon(), "iconmenu" + a->icon().name()).toStdString();
GtkWidget* image = gtk_image_new_from_file(iconPath.c_str());
item = gtk_image_menu_item_new_with_label(aText.c_str());
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
gtk_image_menu_item_set_always_show_image(GTK_IMAGE_MENU_ITEM(item), TRUE);
}
gtk_menu_shell_append(GTK_MENU_SHELL(unityMenu), item);
void (*callback)(GtkMenu*, gpointer data) = [](GtkMenu*, gpointer a) {
static_cast<QAction*>(a)->activate(QAction::Trigger);
};
g_signal_connect(item, "activate", G_CALLBACK(callback), a);
gtk_widget_show(item);
}
app_indicator_set_menu(unityIndicator, GTK_MENU(unityMenu));
DbusmenuServer* menuServer;
DbusmenuMenuitem* rootMenuItem;
g_object_get(unityIndicator, "dbus-menu-server", &menuServer, nullptr);
g_object_get(menuServer, "root-node", &rootMenuItem, nullptr);
void (*callback)(DbusmenuMenuitem*, gpointer) = [](DbusmenuMenuitem*, gpointer data) {
static_cast<SystemTrayIcon*>(data)->activated(QSystemTrayIcon::Unknown);
};
g_signal_connect(rootMenuItem, "about-to-show", G_CALLBACK(callback), this);
}
#endif
else if (backendType == SystrayBackendType::Qt) {
qtIcon->setContextMenu(menu);
}
}
void SystemTrayIcon::show()
{
setVisible(true);
}
void SystemTrayIcon::hide()
{
setVisible(false);
}
void SystemTrayIcon::setVisible(bool newState)
{
if (false)
;
#ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND
else if (backendType == SystrayBackendType::StatusNotifier) {
if (newState)
status_notifier_set_status(statusNotifier, STATUS_NOTIFIER_STATUS_ACTIVE);
else
status_notifier_set_status(statusNotifier, STATUS_NOTIFIER_STATUS_PASSIVE);
}
#endif
#ifdef ENABLE_SYSTRAY_GTK_BACKEND
else if (backendType == SystrayBackendType::GTK) {
if (newState)
gtk_status_icon_set_visible(gtkIcon, true);
else
gtk_status_icon_set_visible(gtkIcon, false);
}
#endif
#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
else if (backendType == SystrayBackendType::Unity) {
if (newState)
app_indicator_set_status(unityIndicator, APP_INDICATOR_STATUS_ACTIVE);
else
app_indicator_set_status(unityIndicator, APP_INDICATOR_STATUS_PASSIVE);
}
#endif
else if (backendType == SystrayBackendType::Qt) {
if (newState)
qtIcon->show();
else
qtIcon->hide();
}
}
void SystemTrayIcon::setIcon(QIcon& icon)
{
if (false)
;
#ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND
else if (backendType == SystrayBackendType::StatusNotifier) {
GdkPixbuf* pixbuf = convertQIconToPixbuf(icon);
status_notifier_set_from_pixbuf(statusNotifier, STATUS_NOTIFIER_ICON, pixbuf);
g_object_unref(pixbuf);
}
#endif
#ifdef ENABLE_SYSTRAY_GTK_BACKEND
else if (backendType == SystrayBackendType::GTK) {
GdkPixbuf* pixbuf = convertQIconToPixbuf(icon);
gtk_status_icon_set_from_pixbuf(gtkIcon, pixbuf);
g_object_unref(pixbuf);
}
#endif
#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
else if (backendType == SystrayBackendType::Unity) {
// Alternate file names or appindicator will not reload the icon
if (app_indicator_get_icon(unityIndicator) == QString("icon2")) {
extractIconToFile(icon, "icon");
app_indicator_set_icon_full(unityIndicator, "icon", "qtox");
} else {
extractIconToFile(icon, "icon2");
app_indicator_set_icon_full(unityIndicator, "icon2", "qtox");
}
}
#endif
else if (backendType == SystrayBackendType::Qt) {
qtIcon->setIcon(icon);
}
}
SystrayBackendType SystemTrayIcon::backend() const
{
return backendType;
}

View File

@ -1,70 +0,0 @@
/*
Copyright © 2015-2019 by The qTox Project Contributors
This file is part of qTox, a Qt-based graphical interface for Tox.
qTox is libre software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
qTox 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 qTox. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SYSTEMTRAYICON_H
#define SYSTEMTRAYICON_H
#include "systemtrayicon_private.h"
#include <QObject>
class QSystemTrayIcon;
class QMenu;
class SystemTrayIcon : public QObject
{
Q_OBJECT
public:
SystemTrayIcon();
~SystemTrayIcon();
void setContextMenu(QMenu* menu);
void show();
void hide();
void setVisible(bool);
void setIcon(QIcon& icon);
SystrayBackendType backend() const;
signals:
void activated(QSystemTrayIcon::ActivationReason);
private:
QString extractIconToFile(QIcon icon, QString name = "icon");
#if defined(ENABLE_SYSTRAY_GTK_BACKEND) || defined(ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND)
static GdkPixbuf* convertQIconToPixbuf(const QIcon& icon);
#endif
private:
SystrayBackendType backendType;
QSystemTrayIcon* qtIcon = nullptr;
#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
AppIndicator* unityIndicator;
GtkWidget* unityMenu;
#endif
#ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND
StatusNotifier* statusNotifier;
GtkWidget* snMenu;
#endif
#ifdef ENABLE_SYSTRAY_GTK_BACKEND
GtkStatusIcon* gtkIcon;
GtkWidget* gtkMenu;
#endif
};
#endif // SYSTEMTRAYICON_H

View File

@ -1,71 +0,0 @@
/*
Copyright © 2015-2019 by The qTox Project Contributors
This file is part of qTox, a Qt-based graphical interface for Tox.
qTox is libre software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
qTox 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 qTox. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SYSTEMTRAYICON_PRIVATE_H
#define SYSTEMTRAYICON_PRIVATE_H
#include <QSystemTrayIcon>
#ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND
#ifdef signals
#undef signals
#endif
extern "C" {
#include "src/platform/statusnotifier/statusnotifier.h"
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gio/gio.h>
#include <glib-object.h>
#include <glib.h>
#include <gtk/gtk.h>
}
#define signals public
#endif
#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
#ifdef signals
#undef signals
#endif
extern "C" {
#include <gtk/gtk.h>
#include <libappindicator/app-indicator.h>
#include <libdbusmenu-glib/server.h>
}
#define signals public
#endif
#ifdef ENABLE_SYSTRAY_GTK_BACKEND
#ifdef signals
#undef signals
#endif
extern "C" {
#include <gtk/gtk.h>
}
#define signals public
#endif
enum class SystrayBackendType
{
Qt,
Unity,
StatusNotifier,
GTK
};
#endif // SYSTEMTRAYICON_PRIVATE_H

View File

@ -46,7 +46,6 @@
#include "groupwidget.h"
#include "maskablepixmapwidget.h"
#include "splitterrestorer.h"
#include "systemtrayicon.h"
#include "form/groupchatform.h"
#include "src/audio/audio.h"
#include "src/chatlog/content/filetransferwidget.h"
@ -584,7 +583,6 @@ Widget::~Widget()
delete form;
}
delete icon;
delete profileForm;
delete profileInfo;
delete addFriendForm;
@ -2251,7 +2249,7 @@ void Widget::onTryCreateTrayIcon()
static int32_t tries = 15;
if (!icon && tries--) {
if (QSystemTrayIcon::isSystemTrayAvailable()) {
icon = new SystemTrayIcon();
icon = std::unique_ptr<QSystemTrayIcon>(new QSystemTrayIcon);
updateIcons();
trayMenu = new QMenu(this);
@ -2266,9 +2264,7 @@ void Widget::onTryCreateTrayIcon()
trayMenu->addAction(actionQuit);
icon->setContextMenu(trayMenu);
// don't activate qTox widget on tray icon click in Unity backend (see #3419)
if (icon->backend() != SystrayBackendType::Unity)
connect(icon, &SystemTrayIcon::activated, this, &Widget::onIconClick);
connect(icon.get(), &QSystemTrayIcon::activated, this, &Widget::onIconClick);
if (settings.getShowSystemTray()) {
icon->show();

View File

@ -277,7 +277,7 @@ private:
void cleanupNotificationSound();
private:
SystemTrayIcon* icon = nullptr;
std::unique_ptr<QSystemTrayIcon> icon;
QMenu* trayMenu;
QAction* statusOnline;
QAction* statusAway;