Skip to content

Commit bbf6edd

Browse files
committed
Refactor tray icon ID type to use IdAllocator
Replaces the TrayIconID typedef (long) with TrayIconId based on IdAllocator::IdType across all platforms and related event classes. Updates method signatures, member variables, and event constructors for consistency and type safety. Minor formatting and whitespace improvements applied in several files.
1 parent 2c56697 commit bbf6edd

14 files changed

+79
-115
lines changed

src/foundation/id_allocator.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ uint32_t IdAllocator::GetSequence(IdType id) {
3131
bool IdAllocator::IsValid(IdType id) {
3232
// Extract type value from high 8 bits
3333
const uint32_t type_value = (id & kTypeMask) >> kTypeShift;
34-
34+
3535
// Extract sequence number from low 24 bits
3636
const uint32_t seq = id & kSequenceMask;
37-
37+
3838
// ID is valid if:
3939
// 1. Type value is in valid range [kMinTypeValue, kMaxTypeValue] (1-10)
4040
// 2. Sequence number is non-zero (0 is reserved for kInvalidId)
@@ -47,10 +47,10 @@ bool IdAllocator::IsValid(IdType id) {
4747
std::pair<uint32_t, uint32_t> IdAllocator::Decompose(IdType id) {
4848
// Extract type value from high 8 bits (bits 31-24)
4949
const uint32_t type_value = (id & kTypeMask) >> kTypeShift;
50-
50+
5151
// Extract sequence number from low 24 bits (bits 23-0)
5252
const uint32_t sequence = id & kSequenceMask;
53-
53+
5454
// Return both components as a pair
5555
return {type_value, sequence};
5656
}

src/foundation/id_allocator.h

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,9 @@ class IdAllocator {
4444
/// Bit layout specification: [ type:8 | sequence:24 ]
4545
/// High 8 bits store the type identifier, low 24 bits store the sequence
4646
/// number
47-
static constexpr uint32_t kTypeBits =
48-
8; ///< Number of bits allocated for type information
49-
static constexpr uint32_t kSequenceBits =
50-
24; ///< Number of bits allocated for sequence numbers
51-
static constexpr uint32_t kTypeShift =
52-
24; ///< Bit shift amount to extract type from ID
47+
static constexpr uint32_t kTypeBits = 8; ///< Number of bits allocated for type information
48+
static constexpr uint32_t kSequenceBits = 24; ///< Number of bits allocated for sequence numbers
49+
static constexpr uint32_t kTypeShift = 24; ///< Bit shift amount to extract type from ID
5350
static constexpr uint32_t kTypeMask =
5451
0xFF000000u; ///< Bit mask to extract type bits (high 8 bits)
5552
static constexpr uint32_t kSequenceMask =
@@ -91,8 +88,7 @@ class IdAllocator {
9188
// once
9289
static uint32_t type_value = []() {
9390
// Atomically get the next available type value
94-
uint32_t value =
95-
GetNextTypeCounter().fetch_add(1, std::memory_order_relaxed);
91+
uint32_t value = GetNextTypeCounter().fetch_add(1, std::memory_order_relaxed);
9692
if (value > kMaxTypeValue) {
9793
// Handle overflow - this shouldn't happen in practice with only 10
9894
// types but provides safety in case of programming errors
@@ -120,8 +116,7 @@ class IdAllocator {
120116
// Using relaxed memory ordering is safe here because we only need
121117
// atomicity, not ordering guarantees between different operations. This
122118
// provides optimal performance while maintaining thread safety.
123-
uint32_t sequence =
124-
GetCounter<T>().fetch_add(1, std::memory_order_relaxed) + 1u;
119+
uint32_t sequence = GetCounter<T>().fetch_add(1, std::memory_order_relaxed) + 1u;
125120

126121
// Check for overflow: if sequence wraps around to 0 in the low 24 bits,
127122
// treat as allocation failure to avoid returning kInvalidId

src/platform/linux/menu_linux.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ MenuItem::MenuItem(void* menu_item)
8585
: id(g_next_menu_item_id++),
8686
pimpl_(new Impl((GtkWidget*)menu_item, MenuItemType::Normal)) {
8787
if (pimpl_->gtk_menu_item_ && pimpl_->type_ != MenuItemType::Separator) {
88-
const char* label = gtk_menu_item_get_label(
89-
GTK_MENU_ITEM(pimpl_->gtk_menu_item_));
88+
const char* label =
89+
gtk_menu_item_get_label(GTK_MENU_ITEM(pimpl_->gtk_menu_item_));
9090
if (label && label[0] != '\0') {
9191
pimpl_->title_ = std::string(label);
9292
} else {

src/platform/linux/tray_manager_linux.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ bool TrayManager::IsSupported() {
6262
#endif
6363
}
6464

65-
std::shared_ptr<TrayIcon> TrayManager::Get(TrayIconID id) {
65+
std::shared_ptr<TrayIcon> TrayManager::Get(TrayIconId id) {
6666
std::lock_guard<std::mutex> lock(mutex_);
6767

6868
auto it = trays_.find(id);

src/platform/macos/tray_icon_macos.mm

Lines changed: 22 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <optional>
12
#include "../../foundation/geometry.h"
23
#include "../../menu.h"
34
#include "../../tray_icon.h"
@@ -10,9 +11,9 @@
1011
// for proper memory management of Objective-C objects.
1112

1213
// 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);
14+
typedef void (^TrayIconClickedBlock)(nativeapi::TrayIconId tray_icon_id, const std::string& button);
15+
typedef void (^TrayIconRightClickedBlock)(nativeapi::TrayIconId tray_icon_id);
16+
typedef void (^TrayIconDoubleClickedBlock)(nativeapi::TrayIconId tray_icon_id);
1617

1718
@interface NSStatusBarButtonTarget : NSObject
1819
@property(nonatomic, assign) nativeapi::TrayIcon* trayIcon;
@@ -86,76 +87,46 @@ - (void)statusItemClicked:(id)sender;
8687
size_t menu_closed_listener_id_;
8788
};
8889

89-
TrayIcon::TrayIcon() {
90-
id = -1;
91-
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-
// Initialize the Impl with the created status item
98-
pimpl_ = std::make_unique<Impl>(status_item);
99-
100-
if (pimpl_->ns_status_bar_button_target_) {
101-
pimpl_->ns_status_bar_button_target_.trayIcon = this;
102-
103-
// 设置默认的 Block 处理器,直接发送事件
104-
pimpl_->ns_status_bar_button_target_.leftClickedBlock =
105-
^(TrayIconID tray_icon_id, const std::string& button) {
106-
try {
107-
EmitSync<TrayIconClickedEvent>(tray_icon_id, button);
108-
} catch (...) {
109-
// Protect against event emission exceptions
110-
}
111-
};
112-
113-
pimpl_->ns_status_bar_button_target_.rightClickedBlock = ^(TrayIconID tray_icon_id) {
114-
try {
115-
EmitSync<TrayIconRightClickedEvent>(tray_icon_id);
116-
} catch (...) {
117-
// Protect against event emission exceptions
118-
}
119-
};
120-
121-
pimpl_->ns_status_bar_button_target_.doubleClickedBlock = ^(TrayIconID tray_icon_id) {
122-
try {
123-
EmitSync<TrayIconDoubleClickedEvent>(tray_icon_id);
124-
} catch (...) {
125-
// Protect against event emission exceptions
126-
}
127-
};
128-
}
90+
TrayIcon::TrayIcon() : TrayIcon(nullptr) {}
91+
92+
TrayIcon::TrayIcon(void* tray) {
93+
id = IdAllocator::Allocate<TrayIcon>();
94+
95+
NSStatusItem* status_item = nullptr;
96+
97+
if (tray == nullptr) {
98+
// Create platform-specific NSStatusItem
99+
NSStatusBar* status_bar = [NSStatusBar systemStatusBar];
100+
status_item = [status_bar statusItemWithLength:NSVariableStatusItemLength];
129101
} else {
130-
// If status_item creation failed, create Impl with nil
131-
pimpl_ = std::make_unique<Impl>(nil);
102+
status_item = (__bridge NSStatusItem*)tray;
132103
}
133-
}
134104

135-
TrayIcon::TrayIcon(void* tray) : pimpl_(std::make_unique<Impl>((__bridge NSStatusItem*)tray)) {
136-
id = -1; // Will be set by TrayManager when created
105+
// Initialize the Impl with the status item
106+
pimpl_ = std::make_unique<Impl>(status_item);
107+
137108
if (pimpl_->ns_status_bar_button_target_) {
138109
pimpl_->ns_status_bar_button_target_.trayIcon = this;
139110

140111
// 设置默认的 Block 处理器,直接发送事件
141112
pimpl_->ns_status_bar_button_target_.leftClickedBlock =
142-
^(TrayIconID tray_icon_id, const std::string& button) {
113+
^(TrayIconId tray_icon_id, const std::string& button) {
143114
try {
144115
EmitSync<TrayIconClickedEvent>(tray_icon_id, button);
145116
} catch (...) {
146117
// Protect against event emission exceptions
147118
}
148119
};
149120

150-
pimpl_->ns_status_bar_button_target_.rightClickedBlock = ^(TrayIconID tray_icon_id) {
121+
pimpl_->ns_status_bar_button_target_.rightClickedBlock = ^(TrayIconId tray_icon_id) {
151122
try {
152123
EmitSync<TrayIconRightClickedEvent>(tray_icon_id);
153124
} catch (...) {
154125
// Protect against event emission exceptions
155126
}
156127
};
157128

158-
pimpl_->ns_status_bar_button_target_.doubleClickedBlock = ^(TrayIconID tray_icon_id) {
129+
pimpl_->ns_status_bar_button_target_.doubleClickedBlock = ^(TrayIconId tray_icon_id) {
159130
try {
160131
EmitSync<TrayIconDoubleClickedEvent>(tray_icon_id);
161132
} catch (...) {

src/platform/macos/tray_manager_macos.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
return true;
5757
}
5858

59-
std::shared_ptr<TrayIcon> TrayManager::Get(TrayIconID id) {
59+
std::shared_ptr<TrayIcon> TrayManager::Get(TrayIconId id) {
6060
std::lock_guard<std::mutex> lock(mutex_);
6161

6262
auto it = trays_.find(id);

src/platform/windows/menu_windows.cpp

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ namespace nativeapi {
1313
static std::atomic<MenuItemID> g_next_menu_item_id{1};
1414
static std::atomic<MenuID> g_next_menu_id{1};
1515

16-
1716
// Helper function to convert KeyboardAccelerator to Windows accelerator
1817
std::pair<UINT, UINT> ConvertAccelerator(
1918
const KeyboardAccelerator& accelerator) {
@@ -127,20 +126,17 @@ class MenuItem::Impl {
127126
}
128127
};
129128

130-
131129
MenuItem::MenuItem(void* native_item)
132130
: id(g_next_menu_item_id++),
133-
pimpl_(std::make_unique<Impl>(nullptr, 0, MenuItemType::Normal)) {
134-
}
131+
pimpl_(std::make_unique<Impl>(nullptr, 0, MenuItemType::Normal)) {}
135132

136133
MenuItem::MenuItem(const std::string& text, MenuItemType type)
137134
: id(g_next_menu_item_id++),
138135
pimpl_(std::make_unique<Impl>(nullptr, 0, type)) {
139136
pimpl_->text_ = text;
140137
}
141138

142-
MenuItem::~MenuItem() {
143-
}
139+
MenuItem::~MenuItem() {}
144140

145141
MenuItemType MenuItem::GetType() const {
146142
return pimpl_->type_;
@@ -320,18 +316,14 @@ class Menu::Impl {
320316
}
321317
};
322318

323-
324319
Menu::Menu(void* native_menu)
325320
: id(g_next_menu_id++),
326-
pimpl_(std::make_unique<Impl>(static_cast<HMENU>(native_menu))) {
327-
}
321+
pimpl_(std::make_unique<Impl>(static_cast<HMENU>(native_menu))) {}
328322

329-
Menu::Menu() : id(g_next_menu_id++),
330-
pimpl_(std::make_unique<Impl>(CreatePopupMenu())) {
331-
}
323+
Menu::Menu()
324+
: id(g_next_menu_id++), pimpl_(std::make_unique<Impl>(CreatePopupMenu())) {}
332325

333-
Menu::~Menu() {
334-
}
326+
Menu::~Menu() {}
335327

336328
void Menu::AddItem(std::shared_ptr<MenuItem> item) {
337329
if (!item)

src/platform/windows/string_utils_windows.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ namespace { // Anonymous namespace, visible only within the translation unit in
99

1010
// Convert std::string (UTF-8) to std::wstring (UTF-16)
1111
inline std::wstring StringToWString(const std::string& str) {
12-
if (str.empty()) return std::wstring();
13-
12+
if (str.empty())
13+
return std::wstring();
14+
1415
int size_needed = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), nullptr, 0);
1516
std::wstring wstr(size_needed, 0);
1617
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), &wstr[0], size_needed);
@@ -19,22 +20,25 @@ inline std::wstring StringToWString(const std::string& str) {
1920

2021
// Convert std::wstring (UTF-16) to std::string (UTF-8)
2122
inline std::string WStringToString(const std::wstring& wstr) {
22-
if (wstr.empty()) return std::string();
23-
24-
int size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), (int)wstr.size(), nullptr, 0, nullptr, nullptr);
23+
if (wstr.empty())
24+
return std::string();
25+
26+
int size_needed =
27+
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), (int)wstr.size(), nullptr, 0, nullptr, nullptr);
2528
std::string str(size_needed, 0);
26-
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), (int)wstr.size(), &str[0], size_needed, nullptr, nullptr);
29+
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), (int)wstr.size(), &str[0], size_needed, nullptr,
30+
nullptr);
2731
return str;
2832
}
2933

3034
// Convert WCHAR array to std::string
3135
inline std::string WCharArrayToString(const WCHAR* wchar_array) {
32-
if (!wchar_array) return std::string();
36+
if (!wchar_array)
37+
return std::string();
3338
return WStringToString(std::wstring(wchar_array));
3439
}
3540

3641
} // anonymous namespace
3742
} // namespace nativeapi
3843

3944
#endif // NATIVEAPI_PLATFORM_WINDOWS_STRING_UTILS_H_
40-

src/platform/windows/tray_icon_windows.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#include <windows.h>
21
#include <shellapi.h>
2+
#include <windows.h>
33
#include <memory>
44
#include <string>
55

@@ -14,8 +14,7 @@ namespace nativeapi {
1414
// Private implementation class
1515
class TrayIcon::Impl {
1616
public:
17-
Impl()
18-
: hwnd_(nullptr), icon_id_(0), icon_handle_(nullptr) {}
17+
Impl() : hwnd_(nullptr), icon_id_(0), icon_handle_(nullptr) {}
1918

2019
Impl(HWND hwnd, UINT icon_id)
2120
: hwnd_(hwnd), icon_id_(icon_id), icon_handle_(nullptr) {
@@ -199,7 +198,7 @@ void TrayIcon::SetTooltip(std::optional<std::string> tooltip) {
199198
if (pimpl_->hwnd_) {
200199
std::string tooltip_str = tooltip.has_value() ? *tooltip : "";
201200
std::wstring wtooltip = StringToWString(tooltip_str);
202-
wcsncpy_s(pimpl_->nid_.szTip, _countof(pimpl_->nid_.szTip),
201+
wcsncpy_s(pimpl_->nid_.szTip, _countof(pimpl_->nid_.szTip),
203202
wtooltip.c_str(), _TRUNCATE);
204203

205204
// Update if icon is visible (check if hIcon is set as indicator)

src/platform/windows/tray_manager_windows.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@
66

77
namespace nativeapi {
88

9-
// Define the Impl class for Windows (empty for now, as Windows doesn't need platform-specific data)
9+
// Define the Impl class for Windows (empty for now, as Windows doesn't need
10+
// platform-specific data)
1011
class TrayManager::Impl {
1112
public:
1213
Impl() {}
1314
~Impl() {}
1415
};
1516

16-
TrayManager::TrayManager() : pimpl_(std::make_unique<Impl>()), next_tray_id_(1) {}
17+
TrayManager::TrayManager()
18+
: pimpl_(std::make_unique<Impl>()), next_tray_id_(1) {}
1719

1820
TrayManager::~TrayManager() {
1921
std::lock_guard<std::mutex> lock(mutex_);
@@ -31,7 +33,7 @@ bool TrayManager::IsSupported() {
3133
return true; // Windows always supports system tray
3234
}
3335

34-
std::shared_ptr<TrayIcon> TrayManager::Get(TrayIconID id) {
36+
std::shared_ptr<TrayIcon> TrayManager::Get(TrayIconId id) {
3537
std::lock_guard<std::mutex> lock(mutex_);
3638

3739
auto it = trays_.find(id);
@@ -51,4 +53,4 @@ std::vector<std::shared_ptr<TrayIcon>> TrayManager::GetAll() {
5153
return trays;
5254
}
5355

54-
} // namespace nativeapi
56+
} // namespace nativeapi

0 commit comments

Comments
 (0)