11#include " tray_icon_c.h"
22#include " ../tray_icon.h"
3+ #include " ../tray_icon_event.h"
34#include < cstring>
45#include < map>
56#include < memory>
67
78using namespace nativeapi ;
89
9- // Internal structure to manage C callbacks
10- struct TrayIconCallbackData {
11- native_tray_icon_left_click_callback_t left_click_callback;
12- native_tray_icon_right_click_callback_t right_click_callback;
13- native_tray_icon_double_click_callback_t double_click_callback;
14- void * left_click_user_data;
15- void * right_click_user_data;
16- void * double_click_user_data;
10+ // Internal structure to manage C event listeners
11+ struct TrayIconListenerData {
12+ native_tray_icon_event_type_t event_type;
13+ native_tray_icon_event_callback_t callback;
14+ void * user_data;
15+ size_t listener_id;
1716};
1817
19- // Global map to store callback data
20- static std::map<native_tray_icon_t , std::shared_ptr<TrayIconCallbackData>> g_tray_icon_callbacks;
18+ // Global maps to store listener data
19+ static std::map<native_tray_icon_t , std::vector<std::shared_ptr<TrayIconListenerData>>> g_tray_icon_listeners;
20+ static size_t g_next_listener_id = 1 ;
2121
2222// TrayIcon C API Implementation
2323
@@ -43,11 +43,11 @@ native_tray_icon_t native_tray_icon_create_from_native(void* native_tray) {
4343
4444void native_tray_icon_destroy (native_tray_icon_t tray_icon) {
4545 if (!tray_icon) return ;
46-
47- // Clean up callbacks
48- auto it = g_tray_icon_callbacks .find (tray_icon);
49- if (it != g_tray_icon_callbacks .end ()) {
50- g_tray_icon_callbacks .erase (it);
46+
47+ // Clean up listeners
48+ auto it = g_tray_icon_listeners .find (tray_icon);
49+ if (it != g_tray_icon_listeners .end ()) {
50+ g_tray_icon_listeners .erase (it);
5151 }
5252
5353 // Note: The actual TrayIcon object is managed by shared_ptr
@@ -215,93 +215,95 @@ bool native_tray_icon_is_visible(native_tray_icon_t tray_icon) {
215215 }
216216}
217217
218- void native_tray_icon_set_on_left_click (native_tray_icon_t tray_icon, native_tray_icon_left_click_callback_t callback, void * user_data) {
219- if (!tray_icon) return ;
220-
221- try {
222- auto tray_icon_ptr = static_cast <TrayIcon*>(tray_icon);
223-
224- // Get or create callback data
225- auto it = g_tray_icon_callbacks.find (tray_icon);
226- if (it == g_tray_icon_callbacks.end ()) {
227- g_tray_icon_callbacks[tray_icon] = std::make_shared<TrayIconCallbackData>();
228- }
229-
230- auto callback_data = g_tray_icon_callbacks[tray_icon];
231- callback_data->left_click_callback = callback;
232- callback_data->left_click_user_data = user_data;
233-
234- if (callback) {
235- tray_icon_ptr->SetOnLeftClick ([callback_data]() {
236- if (callback_data && callback_data->left_click_callback ) {
237- callback_data->left_click_callback (callback_data->left_click_user_data );
238- }
239- });
240- } else {
241- tray_icon_ptr->SetOnLeftClick (nullptr );
242- }
243- } catch (...) {
244- // Ignore exceptions
245- }
246- }
218+ int native_tray_icon_add_listener (native_tray_icon_t tray_icon, native_tray_icon_event_type_t event_type, native_tray_icon_event_callback_t callback, void * user_data) {
219+ if (!tray_icon || !callback) return -1 ;
247220
248- void native_tray_icon_set_on_right_click (native_tray_icon_t tray_icon, native_tray_icon_right_click_callback_t callback, void * user_data) {
249- if (!tray_icon) return ;
250-
251221 try {
252222 auto tray_icon_ptr = static_cast <TrayIcon*>(tray_icon);
253-
254- // Get or create callback data
255- auto it = g_tray_icon_callbacks.find (tray_icon);
256- if (it == g_tray_icon_callbacks.end ()) {
257- g_tray_icon_callbacks[tray_icon] = std::make_shared<TrayIconCallbackData>();
258- }
259-
260- auto callback_data = g_tray_icon_callbacks[tray_icon];
261- callback_data->right_click_callback = callback;
262- callback_data->right_click_user_data = user_data;
263-
264- if (callback) {
265- tray_icon_ptr->SetOnRightClick ([callback_data]() {
266- if (callback_data && callback_data->right_click_callback ) {
267- callback_data->right_click_callback (callback_data->right_click_user_data );
268- }
269- });
270- } else {
271- tray_icon_ptr->SetOnRightClick (nullptr );
223+
224+ // Create listener data
225+ auto listener_data = std::make_shared<TrayIconListenerData>();
226+ listener_data->event_type = event_type;
227+ listener_data->callback = callback;
228+ listener_data->user_data = user_data;
229+ listener_data->listener_id = g_next_listener_id++;
230+
231+ // Get or create listener list for this tray icon
232+ auto & listeners = g_tray_icon_listeners[tray_icon];
233+
234+ // Add event listener based on type
235+ size_t cpp_listener_id = 0 ;
236+ switch (event_type) {
237+ case NATIVE_TRAY_ICON_EVENT_CLICKED:
238+ cpp_listener_id = tray_icon_ptr->AddListener <TrayIconClickedEvent>(
239+ [listener_data](const TrayIconClickedEvent& event) {
240+ if (listener_data && listener_data->callback ) {
241+ native_tray_icon_clicked_event_t c_event;
242+ c_event.tray_icon_id = event.GetTrayIconId ();
243+ strncpy (c_event.button , event.GetButton ().c_str (), sizeof (c_event.button ) - 1 );
244+ c_event.button [sizeof (c_event.button ) - 1 ] = ' \0 ' ;
245+ listener_data->callback (&c_event, listener_data->user_data );
246+ }
247+ });
248+ break ;
249+
250+ case NATIVE_TRAY_ICON_EVENT_RIGHT_CLICKED:
251+ cpp_listener_id = tray_icon_ptr->AddListener <TrayIconRightClickedEvent>(
252+ [listener_data](const TrayIconRightClickedEvent& event) {
253+ if (listener_data && listener_data->callback ) {
254+ native_tray_icon_right_clicked_event_t c_event;
255+ c_event.tray_icon_id = event.GetTrayIconId ();
256+ listener_data->callback (&c_event, listener_data->user_data );
257+ }
258+ });
259+ break ;
260+
261+ case NATIVE_TRAY_ICON_EVENT_DOUBLE_CLICKED:
262+ cpp_listener_id = tray_icon_ptr->AddListener <TrayIconDoubleClickedEvent>(
263+ [listener_data](const TrayIconDoubleClickedEvent& event) {
264+ if (listener_data && listener_data->callback ) {
265+ native_tray_icon_double_clicked_event_t c_event;
266+ c_event.tray_icon_id = event.GetTrayIconId ();
267+ listener_data->callback (&c_event, listener_data->user_data );
268+ }
269+ });
270+ break ;
271+
272+ default :
273+ return -1 ;
272274 }
275+
276+ // Store the C++ listener ID in our data structure
277+ listener_data->listener_id = cpp_listener_id;
278+ listeners.push_back (listener_data);
279+
280+ return static_cast <int >(cpp_listener_id);
273281 } catch (...) {
274- // Ignore exceptions
282+ return - 1 ;
275283 }
276284}
277285
278- void native_tray_icon_set_on_double_click (native_tray_icon_t tray_icon, native_tray_icon_double_click_callback_t callback, void * user_data ) {
279- if (!tray_icon) return ;
280-
286+ bool native_tray_icon_remove_listener (native_tray_icon_t tray_icon, int listener_id ) {
287+ if (!tray_icon) return false ;
288+
281289 try {
282290 auto tray_icon_ptr = static_cast <TrayIcon*>(tray_icon);
283-
284- // Get or create callback data
285- auto it = g_tray_icon_callbacks.find (tray_icon);
286- if (it == g_tray_icon_callbacks.end ()) {
287- g_tray_icon_callbacks[tray_icon] = std::make_shared<TrayIconCallbackData>();
288- }
289-
290- auto callback_data = g_tray_icon_callbacks[tray_icon];
291- callback_data->double_click_callback = callback;
292- callback_data->double_click_user_data = user_data;
293-
294- if (callback) {
295- tray_icon_ptr->SetOnDoubleClick ([callback_data]() {
296- if (callback_data && callback_data->double_click_callback ) {
297- callback_data->double_click_callback (callback_data->double_click_user_data );
291+
292+ // Find and remove the listener
293+ auto it = g_tray_icon_listeners.find (tray_icon);
294+ if (it != g_tray_icon_listeners.end ()) {
295+ auto & listeners = it->second ;
296+ for (auto lit = listeners.begin (); lit != listeners.end (); ++lit) {
297+ if (static_cast <int >((*lit)->listener_id ) == listener_id) {
298+ tray_icon_ptr->RemoveListener ((*lit)->listener_id );
299+ listeners.erase (lit);
300+ return true ;
298301 }
299- });
300- } else {
301- tray_icon_ptr->SetOnDoubleClick (nullptr );
302+ }
302303 }
304+ return false ;
303305 } catch (...) {
304- // Ignore exceptions
306+ return false ;
305307 }
306308}
307309
0 commit comments