1+ #include < iostream>
2+ #include < optional>
3+ #include < string>
4+ #include < unistd.h>
5+
6+ // Platform-specific includes for Linux
7+ #ifdef __linux__
18#include < gdk-pixbuf/gdk-pixbuf.h>
29#include < glib.h>
310#include < gtk/gtk.h>
411#include < libayatana-appindicator/app-indicator.h>
5- #include < iostream>
6- #include < optional>
7- #include < string>
12+ #define HAS_GTK 1
13+ #define HAS_AYATANA_APPINDICATOR 1
14+ #else
15+ #define HAS_GTK 0
16+ #define HAS_AYATANA_APPINDICATOR 0
17+ #endif
18+
819#include " ../../foundation/id_allocator.h"
920#include " ../../image.h"
1021#include " ../../menu.h"
1122#include " ../../tray_icon.h"
12- #include " ../../tray_icon_event.h"
1323
1424namespace nativeapi {
1525
@@ -67,7 +77,9 @@ TrayIcon::TrayIcon(void* tray)
6777
6878TrayIcon::~TrayIcon () {
6979 if (pimpl_->app_indicator_ ) {
80+ app_indicator_set_status (pimpl_->app_indicator_ , APP_INDICATOR_STATUS_PASSIVE);
7081 g_object_unref (pimpl_->app_indicator_ );
82+ pimpl_->app_indicator_ = nullptr ;
7183 }
7284}
7385
@@ -83,15 +95,55 @@ void TrayIcon::SetIcon(std::shared_ptr<Image> image) {
8395 // Store the image reference
8496 pimpl_->image_ = image;
8597
86- if (image) {
87- // For now, use a placeholder implementation
88- // TODO: Implement proper Image to file conversion
89- app_indicator_set_icon_full (pimpl_->app_indicator_ ,
90- " application-default-icon" , " Tray Icon" );
98+ // If no image provided, use default icon
99+ if (!image) {
100+ app_indicator_set_icon_full (pimpl_->app_indicator_ , " application-default-icon" , " Tray Icon" );
101+ return ;
102+ }
103+
104+ // Get the native GdkPixbuf object
105+ GdkPixbuf* pixbuf = static_cast <GdkPixbuf*>(image->GetNativeObject ());
106+ if (!pixbuf) {
107+ app_indicator_set_icon_full (pimpl_->app_indicator_ , " application-default-icon" , " Tray Icon" );
108+ return ;
109+ }
110+
111+ // Create temporary PNG file
112+ char temp_path[] = " /tmp/tray_icon_XXXXXX" ;
113+ int fd = mkstemp (temp_path);
114+ if (fd == -1 ) {
115+ app_indicator_set_icon_full (pimpl_->app_indicator_ , " application-default-icon" , " Tray Icon" );
116+ return ;
117+ }
118+ close (fd);
119+
120+ // Append .png extension
121+ std::string png_path (temp_path);
122+ png_path += " .png" ;
123+
124+ // Save pixbuf to PNG file
125+ GError* error = nullptr ;
126+ gboolean success = gdk_pixbuf_save (pixbuf, png_path.c_str (), " png" , &error, nullptr );
127+
128+ // Always clean up the original temporary file
129+ unlink (temp_path);
130+
131+ if (error) {
132+ g_error_free (error);
133+ }
134+
135+ if (success) {
136+ // Set the icon and schedule cleanup
137+ app_indicator_set_icon_full (pimpl_->app_indicator_ , png_path.c_str (), " " );
138+ g_timeout_add (5000 , [](gpointer data) -> gboolean {
139+ unlink (static_cast <char *>(data));
140+ g_free (data);
141+ return FALSE ; // Don't repeat
142+ }, g_strdup (png_path.c_str ()));
91143 } else {
92- // Use default icon
93- app_indicator_set_icon_full (pimpl_->app_indicator_ ,
94- " application-default-icon " , " Tray Icon " );
144+ // Fallback to default icon
145+ app_indicator_set_icon_full (pimpl_->app_indicator_ , " application-default-icon " , " Tray Icon " );
146+ unlink (png_path. c_str () );
95147 }
96148}
97149
@@ -105,7 +157,7 @@ void TrayIcon::SetTitle(std::optional<std::string> title) {
105157 // environments
106158 if (pimpl_->app_indicator_ ) {
107159 const char * title_str = title.has_value () ? title->c_str () : " " ;
108- app_indicator_set_title (pimpl_->app_indicator_ , title_str);
160+ app_indicator_set_label (pimpl_->app_indicator_ , title_str, NULL );
109161 }
110162}
111163
@@ -132,6 +184,7 @@ void TrayIcon::SetContextMenu(std::shared_ptr<Menu> menu) {
132184 if (pimpl_->app_indicator_ && menu && menu->GetNativeObject ()) {
133185 GtkMenu* gtk_menu = static_cast <GtkMenu*>(menu->GetNativeObject ());
134186 app_indicator_set_menu (pimpl_->app_indicator_ , gtk_menu);
187+ gtk_widget_show_all (GTK_WIDGET (gtk_menu));
135188 }
136189}
137190
0 commit comments