Skip to content

Commit cd6f466

Browse files
committed
Improve tray icon handling on Linux
Refactored platform-specific includes and macros for Linux. Enhanced SetIcon to convert images to temporary PNG files for tray icons, with proper cleanup. Updated SetTitle to use app_indicator_set_label and ensured context menu visibility with gtk_widget_show_all.
1 parent 37dbbb6 commit cd6f466

File tree

1 file changed

+66
-13
lines changed

1 file changed

+66
-13
lines changed

src/platform/linux/tray_icon_linux.cpp

Lines changed: 66 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,25 @@
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

1424
namespace nativeapi {
1525

@@ -67,7 +77,9 @@ TrayIcon::TrayIcon(void* tray)
6777

6878
TrayIcon::~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

Comments
 (0)