Skip to content

Commit 81c3828

Browse files
committed
Refactor tray icon creation for platform abstraction
Moved platform-specific tray icon initialization logic into the TrayIcon constructor for Linux, macOS, and Windows. TrayManager::Create now delegates all platform setup to TrayIcon, simplifying manager code and improving encapsulation. Updated documentation to reflect internal platform-specific setup.
1 parent 16f6c09 commit 81c3828

File tree

8 files changed

+96
-62
lines changed

8 files changed

+96
-62
lines changed

src/platform/linux/tray_icon_linux.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,25 @@ class TrayIcon::Impl {
3030

3131
TrayIcon::TrayIcon() : pimpl_(std::make_unique<Impl>(nullptr)) {
3232
id = -1;
33+
34+
#if HAS_GTK && HAS_AYATANA_APPINDICATOR
35+
// Create a unique ID for this tray icon
36+
static int next_indicator_id = 1;
37+
std::string indicator_id =
38+
"nativeapi-tray-" + std::to_string(next_indicator_id++);
39+
40+
// Create a new tray using AppIndicator
41+
AppIndicator* app_indicator =
42+
app_indicator_new(indicator_id.c_str(),
43+
"application-default-icon", // Default icon name
44+
APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
45+
46+
if (app_indicator) {
47+
// Reinitialize the Impl with the created indicator
48+
pimpl_ = std::make_unique<Impl>(app_indicator);
49+
pimpl_->visible_ = true;
50+
}
51+
#endif
3352
}
3453

3554
TrayIcon::TrayIcon(void* tray)

src/platform/linux/tray_manager_linux.cpp

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -66,20 +66,8 @@ std::shared_ptr<TrayIcon> TrayManager::Create() {
6666
std::lock_guard<std::mutex> lock(mutex_);
6767

6868
#if HAS_GTK && HAS_AYATANA_APPINDICATOR
69-
// Create a unique ID for this tray icon
70-
std::string indicator_id = "nativeapi-tray-" + std::to_string(next_tray_id_);
71-
72-
// Create a new tray using AppIndicator
73-
AppIndicator* app_indicator =
74-
app_indicator_new(indicator_id.c_str(),
75-
"application-default-icon", // Default icon name
76-
APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
77-
78-
if (!app_indicator) {
79-
return nullptr;
80-
}
81-
82-
auto tray = std::make_shared<TrayIcon>((void*)app_indicator);
69+
// Create tray icon with platform-specific initialization handled internally
70+
auto tray = std::make_shared<TrayIcon>();
8371
tray->id = next_tray_id_++;
8472
trays_[tray->id] = tray;
8573

src/platform/macos/tray_icon_macos.mm

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -88,33 +88,43 @@ - (void)statusItemClicked:(id)sender;
8888

8989
TrayIcon::TrayIcon() : pimpl_(std::make_unique<Impl>()) {
9090
id = -1;
91-
if (pimpl_->delegate_) {
92-
pimpl_->delegate_.trayIcon = this;
93-
94-
// 设置默认的 Block 处理器,直接发送事件
95-
pimpl_->delegate_.leftClickedBlock = ^(TrayIconID tray_icon_id, const std::string& button) {
96-
try {
97-
EmitSync<TrayIconClickedEvent>(tray_icon_id, button);
98-
} catch (...) {
99-
// Protect against event emission exceptions
100-
}
101-
};
10291

103-
pimpl_->delegate_.rightClickedBlock = ^(TrayIconID tray_icon_id) {
104-
try {
105-
EmitSync<TrayIconRightClickedEvent>(tray_icon_id);
106-
} catch (...) {
107-
// Protect against event emission exceptions
108-
}
109-
};
110-
111-
pimpl_->delegate_.doubleClickedBlock = ^(TrayIconID tray_icon_id) {
112-
try {
113-
EmitSync<TrayIconDoubleClickedEvent>(tray_icon_id);
114-
} catch (...) {
115-
// Protect against event emission exceptions
116-
}
117-
};
92+
// Create platform-specific NSStatusItem
93+
NSStatusBar* status_bar = [NSStatusBar systemStatusBar];
94+
NSStatusItem* status_item = [status_bar statusItemWithLength:NSVariableStatusItemLength];
95+
96+
if (status_item) {
97+
// Reinitialize the Impl with the created status item
98+
pimpl_ = std::make_unique<Impl>(status_item);
99+
100+
if (pimpl_->delegate_) {
101+
pimpl_->delegate_.trayIcon = this;
102+
103+
// 设置默认的 Block 处理器,直接发送事件
104+
pimpl_->delegate_.leftClickedBlock = ^(TrayIconID tray_icon_id, const std::string& button) {
105+
try {
106+
EmitSync<TrayIconClickedEvent>(tray_icon_id, button);
107+
} catch (...) {
108+
// Protect against event emission exceptions
109+
}
110+
};
111+
112+
pimpl_->delegate_.rightClickedBlock = ^(TrayIconID tray_icon_id) {
113+
try {
114+
EmitSync<TrayIconRightClickedEvent>(tray_icon_id);
115+
} catch (...) {
116+
// Protect against event emission exceptions
117+
}
118+
};
119+
120+
pimpl_->delegate_.doubleClickedBlock = ^(TrayIconID tray_icon_id) {
121+
try {
122+
EmitSync<TrayIconDoubleClickedEvent>(tray_icon_id);
123+
} catch (...) {
124+
// Protect against event emission exceptions
125+
}
126+
};
127+
}
118128
}
119129
}
120130

src/platform/macos/tray_manager_macos.mm

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,8 @@
5959
std::shared_ptr<TrayIcon> TrayManager::Create() {
6060
std::lock_guard<std::mutex> lock(mutex_);
6161

62-
NSStatusBar* status_bar = [NSStatusBar systemStatusBar];
63-
NSStatusItem* status_item = [status_bar statusItemWithLength:NSVariableStatusItemLength];
64-
65-
std::cout << status_item.visible << std::endl;
66-
67-
auto tray = std::make_shared<TrayIcon>((__bridge void*)status_item);
62+
// Create tray icon with platform-specific initialization handled internally
63+
auto tray = std::make_shared<TrayIcon>();
6864
tray->id = next_tray_id_++;
6965
trays_[tray->id] = tray;
7066

src/platform/windows/tray_icon_windows.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,36 @@ class TrayIcon::Impl {
100100

101101
TrayIcon::TrayIcon() : pimpl_(std::make_unique<Impl>()) {
102102
id = -1;
103+
104+
// Create a hidden window for this tray icon
105+
HINSTANCE hInstance = GetModuleHandle(nullptr);
106+
107+
// Register window class for this tray icon
108+
static UINT next_class_id = 1;
109+
std::string class_name =
110+
"NativeAPITrayIcon_" + std::to_string(next_class_id++);
111+
112+
WNDCLASS wc = {};
113+
wc.lpfnWndProc = DefWindowProc;
114+
wc.hInstance = hInstance;
115+
wc.lpszClassName = class_name.c_str();
116+
117+
if (RegisterClass(&wc)) {
118+
// Create hidden message-only window
119+
HWND hwnd =
120+
CreateWindow(class_name.c_str(), "NativeAPI Tray Icon", 0, 0, 0, 0, 0,
121+
HWND_MESSAGE, // Message-only window
122+
nullptr, hInstance, nullptr);
123+
124+
if (hwnd) {
125+
// Generate unique icon ID
126+
static UINT next_icon_id = 1;
127+
UINT icon_id = next_icon_id++;
128+
129+
// Reinitialize the Impl with the created window and icon ID
130+
pimpl_ = std::make_unique<Impl>(hwnd, icon_id);
131+
}
132+
}
103133
}
104134

105135
TrayIcon::TrayIcon(void* tray) : pimpl_(std::make_unique<Impl>()) {

src/platform/windows/tray_manager_windows.cpp

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -90,20 +90,9 @@ bool TrayManager::IsSupported() {
9090
std::shared_ptr<TrayIcon> TrayManager::Create() {
9191
std::lock_guard<std::mutex> lock(mutex_);
9292

93-
if (!pimpl_->hwnd_) {
94-
std::cerr << "TrayManager: Hidden window not available" << std::endl;
95-
return nullptr;
96-
}
97-
93+
// Create tray icon with platform-specific initialization handled internally
9894
auto tray = std::make_shared<TrayIcon>();
9995
tray->id = next_tray_id_++;
100-
101-
// Windows-specific initialization is now handled internally by the TrayIcon
102-
// implementation The platform-specific details are encapsulated within the
103-
// PIMPL pattern
104-
UINT icon_id = pimpl_->next_icon_id_++;
105-
// Platform-specific setup is handled in the TrayIcon constructor and methods
106-
10796
trays_[tray->id] = tray;
10897

10998
return tray;

src/tray_icon.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,9 @@ class TrayIcon : public EventEmitter, public NativeObjectProvider {
6666
/**
6767
* @brief Default constructor for TrayIcon.
6868
*
69-
* Creates a new tray icon instance with default settings.
70-
* The icon will not be visible until Show() is called.
69+
* Creates a new tray icon instance with platform-specific initialization.
70+
* The icon will not be visible until SetVisible(true) is called.
71+
* This constructor handles all platform-specific setup internally.
7172
*/
7273
TrayIcon();
7374

src/tray_manager.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ class TrayManager {
5555
/**
5656
* @brief Create a new system tray icon.
5757
*
58-
* Creates a new tray icon instance and registers it with the manager.
59-
* The tray icon will be assigned a unique ID for future reference.
58+
* Creates a new tray icon instance with platform-specific initialization
59+
* and registers it with the manager. The tray icon will be assigned a
60+
* unique ID for future reference.
6061
*
6162
* @return Shared pointer to the newly created TrayIcon instance
6263
* @note The returned tray icon is automatically managed by this TrayManager

0 commit comments

Comments
 (0)