+#include <gtk/gtk.h>
+
+#if !GTK_CHECK_VERSION(2,10,0)
+ typedef struct _GtkStatusIcon GtkStatusIcon;
+#endif
+
+class wxTaskBarIcon::Private
+{
+public:
+ Private(wxTaskBarIcon* taskBarIcon);
+ ~Private();
+ void SetIcon();
+ void size_allocate(int width, int height);
+
+ // owning wxTaskBarIcon
+ wxTaskBarIcon* m_taskBarIcon;
+ // used when GTK+ >= 2.10
+ GtkStatusIcon* m_statusIcon;
+ // used when GTK+ < 2.10
+ GtkWidget* m_eggTrayIcon;
+ // for PopupMenu
+ wxWindow* m_win;
+ // for tooltip when GTK+ < 2.10
+ GtkTooltips* m_tooltips;
+ wxBitmap m_bitmap;
+ wxString m_tipText;
+ // width and height of available space, only used when GTK+ < 2.10
+ int m_size;
+};
+//-----------------------------------------------------------------------------
+
+extern "C" {
+static void
+icon_size_allocate(GtkWidget*, GtkAllocation* alloc, wxTaskBarIcon::Private* priv)
+{
+ priv->size_allocate(alloc->width, alloc->height);
+}
+
+static void
+icon_destroy(GtkWidget*, wxTaskBarIcon::Private* priv)
+{
+ // Icon window destroyed, probably because tray program has died.
+ // Recreate icon so it will appear if tray program is restarted.
+ priv->m_eggTrayIcon = NULL;
+ priv->SetIcon();
+}
+
+static void
+icon_activate(void*, wxTaskBarIcon* taskBarIcon)
+{
+ // activate occurs from single click with GTK+
+ wxTaskBarIconEvent event(wxEVT_TASKBAR_LEFT_DOWN, taskBarIcon);
+ if (!taskBarIcon->SafelyProcessEvent(event))
+ {
+ // if single click not handled, send double click for compatibility
+ event.SetEventType(wxEVT_TASKBAR_LEFT_DCLICK);
+ taskBarIcon->SafelyProcessEvent(event);
+ }
+}
+
+static gboolean
+icon_popup_menu(GtkWidget*, wxTaskBarIcon* taskBarIcon)
+{
+ wxTaskBarIconEvent event(wxEVT_TASKBAR_CLICK, taskBarIcon);
+ taskBarIcon->SafelyProcessEvent(event);
+ return true;
+}
+
+static gboolean
+icon_button_press_event(GtkWidget*, GdkEventButton* event, wxTaskBarIcon* taskBarIcon)
+{
+ if (event->type == GDK_BUTTON_PRESS)
+ {
+ if (event->button == 1)
+ icon_activate(NULL, taskBarIcon);
+ else if (event->button == 3)
+ icon_popup_menu(NULL, taskBarIcon);
+ }
+ return false;
+}
+
+#if GTK_CHECK_VERSION(2,10,0)
+static void
+status_icon_popup_menu(GtkStatusIcon*, guint, guint, wxTaskBarIcon* taskBarIcon)
+{
+ icon_popup_menu(NULL, taskBarIcon);
+}
+#endif
+} // extern "C"
+//-----------------------------------------------------------------------------
+
+bool wxTaskBarIconBase::IsAvailable()
+{
+ char name[32];
+ g_snprintf(name, sizeof(name), "_NET_SYSTEM_TRAY_S%d",
+ gdk_x11_get_default_screen());
+ Atom atom = gdk_x11_get_xatom_by_name(name);
+
+ Window manager = XGetSelectionOwner(gdk_x11_get_default_xdisplay(), atom);
+
+ return manager != None;
+}
+//-----------------------------------------------------------------------------
+
+wxTaskBarIcon::Private::Private(wxTaskBarIcon* taskBarIcon)
+{
+ m_taskBarIcon = taskBarIcon;
+ m_statusIcon = NULL;
+ m_eggTrayIcon = NULL;
+ m_win = NULL;
+ m_tooltips = NULL;
+ m_size = 0;
+}
+
+wxTaskBarIcon::Private::~Private()
+{
+ if (m_statusIcon)
+ g_object_unref(m_statusIcon);
+ else if (m_eggTrayIcon)
+ {
+ g_signal_handlers_disconnect_by_func(m_eggTrayIcon, (void*)icon_destroy, this);
+ gtk_widget_destroy(m_eggTrayIcon);
+ }
+ if (m_win)
+ {
+ m_win->PopEventHandler();
+ m_win->Destroy();
+ }
+ if (m_tooltips)
+ {
+ gtk_object_destroy(GTK_OBJECT(m_tooltips));
+ g_object_unref(m_tooltips);
+ }
+}