Skip to content

Commit 348eac7

Browse files
committed
feat: Implement Tray and TrayManager classes for macOS
1 parent dd1727f commit 348eac7

File tree

7 files changed

+212
-14
lines changed

7 files changed

+212
-14
lines changed

examples/nswindow_example/main.mm

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include <iostream>
44
#include "nativeapi.h"
55

6+
using nativeapi::Tray;
7+
using nativeapi::TrayManager;
68
using nativeapi::Window;
79
using nativeapi::WindowManager;
810

@@ -68,6 +70,19 @@ - (void)applicationDidFinishLaunching:(NSNotification*)notification {
6870
std::cout << "Size: " << windowSize.width << "x" << windowSize.height
6971
<< std::endl;
7072
}
73+
74+
75+
TrayManager trayManager = TrayManager();
76+
77+
std::shared_ptr<Tray> newTrayPtr = trayManager.Create();
78+
if (newTrayPtr != nullptr) {
79+
Tray& newTray = *newTrayPtr;
80+
newTray.SetTitle("Hello, World!");
81+
std::cout << "Tray ID: " << newTray.id << std::endl;
82+
std::cout << "Tray Title: " << newTray.GetTitle() << std::endl;
83+
} else {
84+
std::cerr << "Failed to create tray." << std::endl;
85+
}
7186
}];
7287
}
7388

examples/window_example/main.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,25 @@ using nativeapi::WindowManager;
77
int main() {
88
WindowManager windowManager = WindowManager();
99

10-
windowManager.Create();
11-
1210
// Get primary display information
13-
Window currentWindow = windowManager.GetCurrent();
14-
std::cout << "Current Window Information:" << std::endl;
15-
std::cout << "ID: " << currentWindow.id << std::endl;
16-
std::cout << "Name: " << currentWindow.name << std::endl;
17-
std::cout << std::endl;
11+
std::shared_ptr<Window> currentWindowPtr = windowManager.GetCurrent();
12+
if (currentWindowPtr != nullptr) {
13+
Window& currentWindow = *currentWindowPtr;
14+
std::cout << "Current Window Information:" << std::endl;
15+
std::cout << "ID: " << currentWindow.id << std::endl;
16+
std::cout << std::endl;
17+
}
1818

19-
// Get all displays information
20-
std::vector<Window> windowList = windowManager.GetAll();
21-
std::cout << "All Windows Information:" << std::endl;
22-
for (int i = 0; i < windowList.size(); i++) {
23-
Window& window = windowList[i];
19+
// Get all windows
20+
std::vector<std::shared_ptr<Window>> windowList = (windowManager.GetAll());
21+
std::cout << "\nAll Windows Information:" << std::endl;
22+
for (size_t i = 0; i < windowList.size(); i++) {
23+
const Window& window = *windowList[i];
2424
std::cout << "Window " << (i + 1) << ":" << std::endl;
2525
std::cout << "ID: " << window.id << std::endl;
26-
std::cout << "Name: " << window.name << std::endl;
27-
std::cout << std::endl;
26+
auto windowSize = window.GetSize();
27+
std::cout << "Size: " << windowSize.width << "x" << windowSize.height
28+
<< std::endl;
2829
}
2930
return 0;
3031
}

include/nativeapi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@
33
#include "../src/display.h"
44
#include "../src/display_manager.h"
55
#include "../src/geometry.h"
6+
#include "../src/tray.h"
7+
#include "../src/tray_manager.h"
68
#include "../src/window.h"
79
#include "../src/window_manager.h"

src/tray.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#pragma once
2+
#include <string>
3+
#include "geometry.h"
4+
5+
namespace nativeapi {
6+
7+
typedef long TrayID;
8+
9+
class Tray {
10+
public:
11+
Tray();
12+
Tray(void* tray);
13+
virtual ~Tray();
14+
15+
TrayID id;
16+
17+
void SetIcon(std::string icon);
18+
19+
void SetTitle(std::string title);
20+
std::string GetTitle();
21+
22+
void SetTooltip(std::string tooltip);
23+
std::string GetTooltip();
24+
25+
Rectangle GetBounds();
26+
27+
private:
28+
class Impl;
29+
Impl* pimpl_;
30+
};
31+
32+
} // namespace nativeapi

src/tray_macos.mm

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include <iostream>
2+
#include "tray.h"
3+
4+
// Import Cocoa headers
5+
#import <Cocoa/Cocoa.h>
6+
7+
namespace nativeapi {
8+
9+
// Private implementation class
10+
class Tray::Impl {
11+
public:
12+
Impl(NSStatusItem* tray) : ns_status_item_(tray) {}
13+
NSStatusItem* ns_status_item_;
14+
};
15+
16+
Tray::Tray() : pimpl_(new Impl(nil)) {
17+
id = -1;
18+
}
19+
20+
Tray::Tray(void* tray) : pimpl_(new Impl((__bridge NSStatusItem*)tray)) {
21+
id = 0;
22+
}
23+
24+
Tray::~Tray() {
25+
delete pimpl_;
26+
}
27+
28+
void Tray::SetIcon(std::string icon) {
29+
// Check if the icon is a base64 string
30+
if (icon.find("data:image") != std::string::npos) {
31+
// Extract the base64 part
32+
size_t pos = icon.find("base64,");
33+
if (pos != std::string::npos) {
34+
std::string base64Icon = icon.substr(pos + 7);
35+
36+
// Convert base64 to NSData
37+
NSData* imageData = [[NSData alloc]
38+
initWithBase64EncodedString:[NSString stringWithUTF8String:base64Icon.c_str()]
39+
options:NSDataBase64DecodingIgnoreUnknownCharacters];
40+
41+
// Create image from data
42+
NSImage* image = [[NSImage alloc] initWithData:imageData];
43+
44+
// Set image size and template property
45+
[image setSize:NSMakeSize(20, 20)]; // Default icon size
46+
[image setTemplate:YES];
47+
48+
// Set the image to the button
49+
[pimpl_->ns_status_item_.button setImage:image];
50+
}
51+
} else {
52+
// Use the icon as a file path or named image
53+
[pimpl_->ns_status_item_.button
54+
setImage:[NSImage imageNamed:[NSString stringWithUTF8String:icon.c_str()]]];
55+
}
56+
}
57+
58+
void Tray::SetTitle(std::string title) {
59+
if (pimpl_->ns_status_item_.button) {
60+
[pimpl_->ns_status_item_.button setTitle:[NSString stringWithUTF8String:title.c_str()]];
61+
}
62+
}
63+
64+
std::string Tray::GetTitle() {
65+
return [pimpl_->ns_status_item_.title UTF8String];
66+
}
67+
68+
void Tray::SetTooltip(std::string tooltip) {
69+
[pimpl_->ns_status_item_.button setToolTip:[NSString stringWithUTF8String:tooltip.c_str()]];
70+
}
71+
72+
std::string Tray::GetTooltip() {
73+
return [[pimpl_->ns_status_item_.button toolTip] UTF8String];
74+
}
75+
76+
} // namespace nativeapi

src/tray_manager.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#pragma once
2+
3+
#include <memory>
4+
#include <unordered_map>
5+
#include <vector>
6+
7+
#include "tray.h"
8+
9+
namespace nativeapi {
10+
11+
// WindowManager is a singleton that manages all windows on the system.
12+
class TrayManager {
13+
public:
14+
TrayManager();
15+
virtual ~TrayManager();
16+
17+
// Create a new tray.
18+
std::shared_ptr<Tray> Create();
19+
20+
// Get a tray by its ID. Returns nullptr if tray not found.
21+
std::shared_ptr<Tray> Get(TrayID id);
22+
23+
// Get all trays.
24+
std::vector<std::shared_ptr<Tray>> GetAll();
25+
26+
private:
27+
// Store tray instances
28+
std::unordered_map<TrayID, std::shared_ptr<Tray>> trays_;
29+
};
30+
31+
} // namespace nativeapi

src/tray_manager_macos.mm

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#include <cstring>
2+
#include <iostream>
3+
#include <string>
4+
5+
#include "tray.h"
6+
#include "tray_manager.h"
7+
8+
// Import Cocoa headers
9+
#import <Cocoa/Cocoa.h>
10+
11+
namespace nativeapi {
12+
13+
TrayManager::TrayManager() {}
14+
15+
TrayManager::~TrayManager() {}
16+
17+
std::shared_ptr<Tray> TrayManager::Create() {
18+
NSStatusBar* status_bar = [NSStatusBar systemStatusBar];
19+
NSStatusItem* status_item = [status_bar statusItemWithLength:NSVariableStatusItemLength];
20+
auto tray = std::make_shared<Tray>((__bridge void*)status_item);
21+
trays_[tray->id] = tray;
22+
return tray;
23+
}
24+
25+
std::shared_ptr<Tray> TrayManager::Get(TrayID id) {
26+
auto it = trays_.find(id);
27+
if (it != trays_.end()) {
28+
return it->second;
29+
}
30+
return nullptr;
31+
}
32+
33+
std::vector<std::shared_ptr<Tray>> TrayManager::GetAll() {
34+
std::vector<std::shared_ptr<Tray>> trays;
35+
for (auto& tray : trays_) {
36+
trays.push_back(tray.second);
37+
}
38+
return trays;
39+
}
40+
41+
} // namespace nativeapi

0 commit comments

Comments
 (0)