1010// for proper memory management of Objective-C objects.
1111
1212// Forward declarations
13+ typedef void (^TrayIconClickedBlock)(nativeapi::TrayIconID tray_icon_id, const std::string& button);
14+ typedef void (^TrayIconRightClickedBlock)(nativeapi::TrayIconID tray_icon_id);
15+ typedef void (^TrayIconDoubleClickedBlock)(nativeapi::TrayIconID tray_icon_id);
16+
1317@interface TrayIconDelegate : NSObject
1418@property (nonatomic , assign ) nativeapi::TrayIcon* trayIcon;
19+ @property (nonatomic , copy ) TrayIconClickedBlock leftClickedBlock;
20+ @property (nonatomic , copy ) TrayIconRightClickedBlock rightClickedBlock;
21+ @property (nonatomic , copy ) TrayIconDoubleClickedBlock doubleClickedBlock;
1522- (void )statusItemClicked : (id )sender ;
16- - (void )statusItemRightClicked : (id )sender ;
1723@end
1824
1925@interface TrayIconMenuDelegate : NSObject <NSMenuDelegate >
@@ -48,14 +54,17 @@ @interface TrayIconMenuDelegate : NSObject <NSMenuDelegate>
4854 }
4955
5056 ~Impl () {
51- // First, clean up delegates to prevent callbacks
57+ // Clean up blocks first
5258 if (delegate_) {
53- delegate_.trayIcon = nullptr ; // Clear the raw pointer first
59+ delegate_.leftClickedBlock = nil ;
60+ delegate_.rightClickedBlock = nil ;
61+ delegate_.doubleClickedBlock = nil ;
62+ delegate_.trayIcon = nullptr ;
5463 delegate_ = nil ;
5564 }
5665
5766 if (menu_delegate_) {
58- menu_delegate_.trayIcon = nullptr ; // Clear the raw pointer first
67+ menu_delegate_.trayIcon = nullptr ;
5968 menu_delegate_ = nil ;
6069 }
6170
@@ -88,6 +97,31 @@ @interface TrayIconMenuDelegate : NSObject <NSMenuDelegate>
8897 id = -1 ;
8998 if (pimpl_->delegate_ ) {
9099 pimpl_->delegate_ .trayIcon = this ;
100+
101+ // 设置默认的 Block 处理器,直接发送事件
102+ pimpl_->delegate_ .leftClickedBlock = ^(TrayIconID tray_icon_id, const std::string& button) {
103+ try {
104+ EmitSync<TrayIconClickedEvent>(tray_icon_id, button);
105+ } catch (...) {
106+ // Protect against event emission exceptions
107+ }
108+ };
109+
110+ pimpl_->delegate_ .rightClickedBlock = ^(TrayIconID tray_icon_id) {
111+ try {
112+ EmitSync<TrayIconRightClickedEvent>(tray_icon_id);
113+ } catch (...) {
114+ // Protect against event emission exceptions
115+ }
116+ };
117+
118+ pimpl_->delegate_ .doubleClickedBlock = ^(TrayIconID tray_icon_id) {
119+ try {
120+ EmitSync<TrayIconDoubleClickedEvent>(tray_icon_id);
121+ } catch (...) {
122+ // Protect against event emission exceptions
123+ }
124+ };
91125 }
92126 if (pimpl_->menu_delegate_ ) {
93127 pimpl_->menu_delegate_ .trayIcon = this ;
@@ -98,6 +132,31 @@ @interface TrayIconMenuDelegate : NSObject <NSMenuDelegate>
98132 id = -1 ; // Will be set by TrayManager when created
99133 if (pimpl_->delegate_ ) {
100134 pimpl_->delegate_ .trayIcon = this ;
135+
136+ // 设置默认的 Block 处理器,直接发送事件
137+ pimpl_->delegate_ .leftClickedBlock = ^(TrayIconID tray_icon_id, const std::string& button) {
138+ try {
139+ EmitSync<TrayIconClickedEvent>(tray_icon_id, button);
140+ } catch (...) {
141+ // Protect against event emission exceptions
142+ }
143+ };
144+
145+ pimpl_->delegate_ .rightClickedBlock = ^(TrayIconID tray_icon_id) {
146+ try {
147+ EmitSync<TrayIconRightClickedEvent>(tray_icon_id);
148+ } catch (...) {
149+ // Protect against event emission exceptions
150+ }
151+ };
152+
153+ pimpl_->delegate_ .doubleClickedBlock = ^(TrayIconID tray_icon_id) {
154+ try {
155+ EmitSync<TrayIconDoubleClickedEvent>(tray_icon_id);
156+ } catch (...) {
157+ // Protect against event emission exceptions
158+ }
159+ };
101160 }
102161 if (pimpl_->menu_delegate_ ) {
103162 pimpl_->menu_delegate_ .trayIcon = this ;
@@ -295,35 +354,8 @@ @interface TrayIconMenuDelegate : NSObject <NSMenuDelegate>
295354 return pimpl_->context_menu_ ->Close ();
296355}
297356
298- // Internal method to handle click events
299- void TrayIcon::HandleLeftClick () {
300- try {
301- EmitSync<TrayIconClickedEvent>(id , " left" );
302- } catch (...) {
303- // Protect against event emission exceptions
304- }
305- }
306-
307- void TrayIcon::HandleRightClick () {
308- try {
309- EmitSync<TrayIconRightClickedEvent>(id );
310- } catch (...) {
311- // Protect against event emission exceptions
312- }
313- }
314-
315- void TrayIcon::HandleDoubleClick () {
316- try {
317- EmitSync<TrayIconDoubleClickedEvent>(id );
318- } catch (...) {
319- // Protect against event emission exceptions
320- }
321- }
322-
323- void TrayIcon::ClearStatusItemMenu () {
324- if (pimpl_->ns_status_item_ ) {
325- pimpl_->ns_status_item_ .menu = nil ;
326- }
357+ void * TrayIcon::GetNativeObjectInternal () const {
358+ return (__bridge void *)pimpl_->ns_status_item_ ;
327359}
328360
329361} // namespace nativeapi
@@ -345,29 +377,28 @@ - (void)statusItemClicked:(id)sender {
345377 if (!event)
346378 return ;
347379
348- // Check the type of click
380+ // Check the type of click and call appropriate block
349381 if (event.type == NSEventTypeRightMouseUp ||
350382 (event.type == NSEventTypeLeftMouseUp &&
351383 (event.modifierFlags & NSEventModifierFlagControl))) {
352384 // Right click or Ctrl+Left click
353- trayIcon->HandleRightClick ();
385+ if (_rightClickedBlock) {
386+ _rightClickedBlock (trayIcon->id );
387+ }
354388 } else if (event.type == NSEventTypeLeftMouseUp) {
355389 // Check for double click
356390 if (event.clickCount == 2 ) {
357- trayIcon->HandleDoubleClick ();
391+ if (_doubleClickedBlock) {
392+ _doubleClickedBlock (trayIcon->id );
393+ }
358394 } else {
359- trayIcon->HandleLeftClick ();
395+ if (_leftClickedBlock) {
396+ _leftClickedBlock (trayIcon->id , " left" );
397+ }
360398 }
361399 }
362400}
363401
364- - (void )statusItemRightClicked : (id )sender {
365- // Check if trayIcon is still valid before proceeding
366- if (_trayIcon) {
367- _trayIcon->HandleRightClick ();
368- }
369- }
370-
371402@end
372403
373404// Implementation of TrayIconMenuDelegate
@@ -376,8 +407,9 @@ @implementation TrayIconMenuDelegate
376407- (void )menuDidClose : (NSMenu *)menu {
377408 // Check if trayIcon is still valid before proceeding
378409 if (_trayIcon) {
410+ NSStatusItem * ns_status_item_ = (__bridge NSStatusItem *)_trayIcon->GetNativeObject ();
379411 // Call a public method to clear the menu (we'll add this method)
380- _trayIcon-> ClearStatusItemMenu () ;
412+ ns_status_item_. menu = nil ;
381413 }
382414}
383415
0 commit comments