1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

Merge branch 'gtktrayicon'

This commit is contained in:
tux3 2015-02-25 00:36:34 +01:00
commit 5dce927292
No known key found for this signature in database
GPG Key ID: 7E086DD661263264
4 changed files with 148 additions and 8 deletions

View File

@ -237,6 +237,30 @@ contains(ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND, NO) {
} }
} }
# The systray GTK backend implements a system tray icon compatible with many systems
unix:!macx:!android {
contains(ENABLE_SYSTRAY_GTK_BACKEND, NO) {
} else {
DEFINES += ENABLE_SYSTRAY_GTK_BACKEND
INCLUDEPATH += "/usr/include/gtk-2.0"
INCLUDEPATH += "/usr/include/glib-2.0"
INCLUDEPATH += "/usr/lib/glib-2.0/include"
INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/glib-2.0/include"
INCLUDEPATH += "/usr/lib/i386-linux-gnu/glib-2.0/include"
INCLUDEPATH += "/usr/lib/gtk-2.0/include"
INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/gtk-2.0/include"
INCLUDEPATH += "/usr/lib/i386-linux-gnu/gtk-2.0/include"
INCLUDEPATH += "/usr/include/atk-1.0"
INCLUDEPATH += "/usr/include/gdk-pixbuf-2.0"
INCLUDEPATH += "/usr/include/cairo"
INCLUDEPATH += "/usr/include/pango-1.0"
LIBS += -lglib-2.0 -lgdk_pixbuf-2.0 -lgio-2.0 -lcairo -lgtk-x11-2.0 -lgdk-x11-2.0 -lgobject-2.0
}
}
!android { !android {
HEADERS += \ HEADERS += \
src/friend.h \ src/friend.h \

View File

@ -37,6 +37,42 @@ SystemTrayIcon::SystemTrayIcon()
app_indicator_set_menu(unityIndicator, GTK_MENU(unityMenu)); app_indicator_set_menu(unityIndicator, GTK_MENU(unityMenu));
} }
#endif #endif
#ifdef ENABLE_SYSTRAY_GTK_BACKEND
else if (desktop == "xfce" || (desktop == "kde"
&& getenv("KDE_SESSION_VERSION") == QString("4")))
{
qDebug() << "SystemTrayIcon: Using GTK backend";
backendType = SystrayBackendType::GTK;
gtk_init(nullptr, nullptr);
void (*callbackFreeImage)(guchar*, gpointer) =
[](guchar*, gpointer image)
{
delete reinterpret_cast<QImage*>(image);
};
QImage* image = new QImage(":/img/icon.png");
if (image->format() != QImage::Format_RGBA8888_Premultiplied)
*image = image->convertToFormat(QImage::Format_RGBA8888_Premultiplied);
GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(image->bits(), GDK_COLORSPACE_RGB, image->hasAlphaChannel(),
8, image->width(), image->height(),
image->bytesPerLine(), callbackFreeImage, image);
gtkIcon = gtk_status_icon_new_from_pixbuf(pixbuf);
gtkMenu = gtk_menu_new();
void (*callbackTrigger)(GtkStatusIcon*, gpointer) =
[](GtkStatusIcon*, gpointer data)
{
((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)
((SystemTrayIcon*)data)->activated(QSystemTrayIcon::MiddleClick);
};
g_signal_connect(gtkIcon, "button-release-event", G_CALLBACK(callbackButtonClick), this);
}
#endif
#ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND #ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND
else if (desktop == "kde" else if (desktop == "kde"
&& getenv("KDE_SESSION_VERSION") == QString("5")) && getenv("KDE_SESSION_VERSION") == QString("5"))
@ -156,6 +192,51 @@ void SystemTrayIcon::setContextMenu(QMenu* menu)
g_signal_connect(statusNotifier, "context-menu", G_CALLBACK(callbackMenu), this); g_signal_connect(statusNotifier, "context-menu", G_CALLBACK(callbackMenu), this);
} }
#endif #endif
#ifdef ENABLE_SYSTRAY_GTK_BACKEND
else if (backendType == SystrayBackendType::GTK)
{
for (QAction* a : menu->actions())
{
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
{
void (*callbackFreeImage)(guchar*, gpointer) =
[](guchar*, gpointer image)
{
delete reinterpret_cast<QImage*>(image);
};
QImage* image = new QImage(a->icon().pixmap(64, 64).toImage());
if (image->format() != QImage::Format_RGBA8888_Premultiplied)
*image = image->convertToFormat(QImage::Format_RGBA8888_Premultiplied);
GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(image->bits(), GDK_COLORSPACE_RGB, image->hasAlphaChannel(),
8, image->width(), image->height(),
image->bytesPerLine(), callbackFreeImage, image);
item = gtk_image_menu_item_new_with_label(aText.toStdString().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);
}
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)(StatusNotifier*, gint, gint, gpointer) =
[](StatusNotifier*, gint, gint, gpointer data)
{
gtk_widget_show_all(((SystemTrayIcon*)data)->gtkMenu);
gtk_menu_popup(GTK_MENU(((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 #ifdef ENABLE_SYSTRAY_UNITY_BACKEND
else if (backendType == SystrayBackendType::Unity) else if (backendType == SystrayBackendType::Unity)
{ {
@ -224,6 +305,15 @@ void SystemTrayIcon::setVisible(bool newState)
status_notifier_set_status(statusNotifier, STATUS_NOTIFIER_STATUS_PASSIVE); status_notifier_set_status(statusNotifier, STATUS_NOTIFIER_STATUS_PASSIVE);
} }
#endif #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 #ifdef ENABLE_SYSTRAY_UNITY_BACKEND
else if (backendType == SystrayBackendType::Unity) else if (backendType == SystrayBackendType::Unity)
{ {
@ -262,6 +352,23 @@ void SystemTrayIcon::setIcon(QIcon &&icon)
status_notifier_set_from_pixbuf(statusNotifier, STATUS_NOTIFIER_ICON, pixbuf); status_notifier_set_from_pixbuf(statusNotifier, STATUS_NOTIFIER_ICON, pixbuf);
} }
#endif #endif
#ifdef ENABLE_SYSTRAY_GTK_BACKEND
else if (backendType == SystrayBackendType::GTK)
{
void (*callbackFreeImage)(guchar*, gpointer) =
[](guchar*, gpointer image)
{
delete reinterpret_cast<QImage*>(image);
};
QImage* image = new QImage(icon.pixmap(64, 64).toImage());
if (image->format() != QImage::Format_RGBA8888_Premultiplied)
*image = image->convertToFormat(QImage::Format_RGBA8888_Premultiplied);
GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(image->bits(), GDK_COLORSPACE_RGB, image->hasAlphaChannel(),
8, image->width(), image->height(),
image->bytesPerLine(), callbackFreeImage, image);
gtk_status_icon_set_from_pixbuf(gtkIcon, pixbuf);
}
#endif
#ifdef ENABLE_SYSTRAY_UNITY_BACKEND #ifdef ENABLE_SYSTRAY_UNITY_BACKEND
else if (backendType == SystrayBackendType::Unity) else if (backendType == SystrayBackendType::Unity)
{ {

View File

@ -36,6 +36,10 @@ private:
StatusNotifier* statusNotifier; StatusNotifier* statusNotifier;
GtkWidget* snMenu; GtkWidget* snMenu;
#endif #endif
#ifdef ENABLE_SYSTRAY_GTK_BACKEND
GtkStatusIcon* gtkIcon;
GtkWidget* gtkMenu;
#endif
}; };
#endif // SYSTEMTRAYICON_H #endif // SYSTEMTRAYICON_H

View File

@ -30,6 +30,17 @@ extern "C" {
#define signals public #define signals public
#endif #endif
#ifdef ENABLE_SYSTRAY_GTK_BACKEND
#ifdef signals
#undef signals
#endif
extern "C" {
#include <libappindicator/app-indicator.h>
#include <gtk/gtk.h>
}
#define signals public
#endif
enum class SystrayBackendType enum class SystrayBackendType
{ {
Qt, Qt,
@ -40,15 +51,9 @@ enum class SystrayBackendType
#ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND #ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND
StatusNotifier, StatusNotifier,
#endif #endif
}; #ifdef ENABLE_SYSTRAY_GTK_BACKEND
GTK,
union SystrayBackend
{
QSystemTrayIcon *qt;
#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
AppIndicator *unity;
#endif #endif
}; };
#endif // SYSTEMTRAYICON_PRIVATE_H #endif // SYSTEMTRAYICON_PRIVATE_H