diff --git a/qtox.pro b/qtox.pro index c1ba213f3..8b5074754 100644 --- a/qtox.pro +++ b/qtox.pro @@ -65,9 +65,9 @@ contains(ENABLE_SYSTRAY_UNITY_BACKEND, YES) { INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/gtk-2.0/include" INCLUDEPATH += "/usr/include/gdk-pixbuf-2.0" INCLUDEPATH += "/usr/include/atk-1.0" + INCLUDEPATH += "/usr/include/libdbusmenu-glib-0.4" - LIBS += -L/usr/lib/x86_64-linux-gnu -lappindicator - LIBS += -L/usr/lib/x86_64-linux-gnu -lgtk-x11-2.0 + LIBS += -lgobject-2.0 -lappindicator -lgtk-x11-2.0 } contains(DISABLE_PLATFORM_EXT, YES) { diff --git a/src/widget/systemtrayicon.cpp b/src/widget/systemtrayicon.cpp index bfb44873d..aacabb4ed 100644 --- a/src/widget/systemtrayicon.cpp +++ b/src/widget/systemtrayicon.cpp @@ -1,7 +1,11 @@ #include "systemtrayicon.h" #include #include +#include +#include #include +#include +#include "src/misc/settings.h" SystemTrayIcon::SystemTrayIcon() { @@ -10,8 +14,25 @@ SystemTrayIcon::SystemTrayIcon() #ifdef ENABLE_SYSTRAY_UNITY_BACKEND else if (desktop.toLower() == "unity") { + QString settingsDir = Settings::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(); + unityIndicator = app_indicator_new_with_path( + "qTox", + "icon", + APP_INDICATOR_CATEGORY_APPLICATION_STATUS, + settingsDir.toStdString().c_str() + ); + app_indicator_set_menu(unityIndicator, GTK_MENU(unityMenu)); } #endif else @@ -21,13 +42,59 @@ SystemTrayIcon::SystemTrayIcon() } } +QString SystemTrayIcon::extractIconToFile(QIcon icon, QString name) +{ + QString iconPath; +#ifdef ENABLE_SYSTRAY_UNITY_BACKEND + iconPath = Settings::getSettingsDirPath()+"/"+name+".png"; + QSize iconSize = icon.actualSize(QSize{64,64}); + icon.pixmap(iconSize).save(iconPath); +#endif + return iconPath; +} + void SystemTrayIcon::setContextMenu(QMenu* menu) { if (false); #ifdef ENABLE_SYSTRAY_UNITY_BACKEND else if (backendType == SystrayBackendType::Unity) { - qCritical() << "SystemTrayIcon::setContextMenu: Not implemented with Unity backend"; + for (QAction* a : menu->actions()) + { + gtk_image_menu_item_new(); + QString aText = a->text().replace('&',""); + GtkWidget* item; + if (a->isSeparator()) + item = gtk_menu_item_new(); + else if (a->icon().isNull()) + item = gtk_menu_item_new_with_label(aText.toStdString().c_str()); + else + { + QString iconPath = extractIconToFile(a->icon(),"iconmenu"+a->icon().name()); + GtkWidget* image = gtk_image_new_from_file(iconPath.toStdString().c_str()); + item = gtk_image_menu_item_new_with_label(aText.toStdString().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) + { + ((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, NULL); + g_object_get(menuServer, "root-node", &rootMenuItem, NULL); + void (*callback)(DbusmenuMenuitem *, gpointer) = + [](DbusmenuMenuitem *, gpointer data) + { + ((SystemTrayIcon*)data)->activated(QSystemTrayIcon::Unknown); + }; + g_signal_connect(rootMenuItem, "about-to-show", G_CALLBACK(callback), this); } #endif else @@ -52,7 +119,10 @@ void SystemTrayIcon::setVisible(bool newState) #ifdef ENABLE_SYSTRAY_UNITY_BACKEND else if (backendType == SystrayBackendType::Unity) { - qCritical() << "SystemTrayIcon::setVisible: Not implemented with Unity backend"; + if (newState) + app_indicator_set_status(unityIndicator, APP_INDICATOR_STATUS_ACTIVE); + else + app_indicator_set_status(unityIndicator, APP_INDICATOR_STATUS_PASSIVE); } #endif else @@ -70,7 +140,17 @@ void SystemTrayIcon::setIcon(QIcon &&icon) #ifdef ENABLE_SYSTRAY_UNITY_BACKEND else if (backendType == SystrayBackendType::Unity) { - qCritical() << "SystemTrayIcon::setIcon: Not implemented with Unity backend"; + // 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 diff --git a/src/widget/systemtrayicon.h b/src/widget/systemtrayicon.h index 1bc6895fb..aa5120cd0 100644 --- a/src/widget/systemtrayicon.h +++ b/src/widget/systemtrayicon.h @@ -21,6 +21,9 @@ public: signals: void activated(QSystemTrayIcon::ActivationReason); +private: + QString extractIconToFile(QIcon icon, QString name="icon"); + private: SystrayBackendType backendType; QSystemTrayIcon* qtIcon; diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 4b81d1900..65541a2eb 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -622,6 +622,10 @@ void Widget::onIconClick(QSystemTrayIcon::ActivationReason reason) case QSystemTrayIcon::MiddleClick: hide(); break; + case QSystemTrayIcon::Unknown: + if (isHidden()) + forceShow(); + break; default: break; }