Skip to content

Commit 6d368cf

Browse files
committed
fix(linux): run notify and acknowledge in async in event loop
1 parent df9af11 commit 6d368cf

1 file changed

Lines changed: 47 additions & 22 deletions

File tree

src/tray_linux.cpp

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,26 @@ namespace tray_linux {
5757
/**
5858
* @brief Acknowledge/click current notification
5959
* @param run_callback - Run notification callback when acknowledging
60+
* @param async - Acknowledge asynchronously in the event loop (default: true)
6061
*/
61-
void acknowledge_notification(const bool run_callback = false) {
62+
void acknowledge_notification(const bool run_callback = false, const bool async = true) {
6263
if (notify_is_initted()) {
6364
std::scoped_lock lock(notification_mutex);
6465
if (notification_current != nullptr && NOTIFY_IS_NOTIFICATION(notification_current)) {
6566
if (run_callback && notification_current_callback != nullptr) {
6667
notification_current_callback();
6768
}
68-
notify_notification_close(notification_current, nullptr);
69-
g_object_unref(G_OBJECT(notification_current));
69+
GSourceFunc f = [](gpointer data) -> gboolean {
70+
auto n = static_cast<NotifyNotification *>(data);
71+
notify_notification_close(n, nullptr);
72+
g_object_unref(G_OBJECT(n));
73+
return false; // Run once then remove from queue
74+
};
75+
if (async) {
76+
g_idle_add(f, notification_current);
77+
} else {
78+
f(notification_current);
79+
}
7080
notification_current = nullptr;
7181
notification_current_callback = nullptr;
7282
}
@@ -75,6 +85,36 @@ namespace tray_linux {
7585
}
7686
}
7787

88+
/**
89+
* @brief Show tray notification via desktop-independent interface async via g_idle_add
90+
* @param data Tray structure containing notification information as a gpointer
91+
* @return false to run just once
92+
*/
93+
gboolean async_notify_(const gpointer data) {
94+
auto tray = static_cast<struct tray *>(data);
95+
if (notification_current != nullptr) {
96+
acknowledge_notification(false, false);
97+
}
98+
std::scoped_lock lock(notification_mutex);
99+
std::filesystem::path notification_icon = tray->notification_icon != nullptr ? tray->notification_icon : tray->icon;
100+
if (std::filesystem::exists(notification_icon)) {
101+
// Use absolute path for filesystem icon files, not a relative one
102+
notification_icon = std::filesystem::absolute(notification_icon);
103+
}
104+
notification_current = notify_notification_new(tray->notification_title, tray->notification_text, notification_icon.c_str());
105+
if (notification_current != nullptr && NOTIFY_IS_NOTIFICATION(notification_current)) {
106+
if (tray->notification_cb != nullptr) {
107+
notification_current_callback = tray->notification_cb;
108+
notify_notification_add_action(notification_current, "default", "Default", NOTIFY_ACTION_CALLBACK(tray->notification_cb), nullptr, nullptr);
109+
}
110+
// Fallback to QtTrayMenu notification if notificaton_show fails
111+
if (!notify_notification_show(notification_current, nullptr) && qt_tray_menu != nullptr && QtTrayMenu::supportsMessages()) {
112+
qt_tray_menu->showMessage(tray->notification_title, tray->notification_text, tray->notification_icon, tray->notification_cb);
113+
}
114+
}
115+
return false; // Run once then remove from queue
116+
}
117+
78118
/**
79119
* @brief Show tray notification via desktop-independent interface
80120
* @param tray Tray structure containing notification information
@@ -85,25 +125,10 @@ namespace tray_linux {
85125
}
86126
// Try to notify using libnotify
87127
if (notify_is_initted()) {
88-
if (notification_current != nullptr) {
89-
acknowledge_notification();
90-
}
91-
std::scoped_lock lock(notification_mutex);
92-
std::filesystem::path notification_icon = tray->notification_icon != nullptr ? tray->notification_icon : tray->icon;
93-
if (std::filesystem::exists(notification_icon)) {
94-
// Use absolute path for filesystem icon files, not a relative one
95-
notification_icon = std::filesystem::absolute(notification_icon);
96-
}
97-
notification_current = notify_notification_new(tray->notification_title, tray->notification_text, notification_icon.c_str());
98-
if (notification_current != nullptr && NOTIFY_IS_NOTIFICATION(notification_current)) {
99-
if (tray->notification_cb != nullptr) {
100-
notification_current_callback = tray->notification_cb;
101-
notify_notification_add_action(notification_current, "default", "Default", NOTIFY_ACTION_CALLBACK(tray->notification_cb), nullptr, nullptr);
102-
}
103-
if (notify_notification_show(notification_current, nullptr)) {
104-
return;
105-
}
106-
}
128+
// Fix tray icon path
129+
130+
// Show tray icon aync via event loop
131+
g_idle_add(async_notify_, tray);
107132
}
108133
// Fallback to QtTrayMenu notification
109134
if (qt_tray_menu != nullptr && QtTrayMenu::supportsMessages()) {

0 commit comments

Comments
 (0)