plusui-native-core 0.1.106 → 0.1.107

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/Core/.cache/clangd/index/api.hpp.016B34C8046EF490.idx +0 -0
  2. package/Core/.cache/clangd/index/app.cpp.1E6FAF043D496421.idx +0 -0
  3. package/Core/.cache/clangd/index/app.hpp.FA0E5D412C4E6148.idx +0 -0
  4. package/Core/.cache/clangd/index/browser.cpp.9461A2CAF129F1D9.idx +0 -0
  5. package/Core/.cache/clangd/index/browser.hpp.BE40AE80881B3107.idx +0 -0
  6. package/Core/.cache/clangd/index/clipboard.cpp.2399913537B2A7AD.idx +0 -0
  7. package/Core/.cache/clangd/index/clipboard.hpp.C1095DDACD7149E9.idx +0 -0
  8. package/Core/.cache/clangd/index/connect.cpp.518C66C7C28B30A9.idx +0 -0
  9. package/Core/.cache/clangd/index/connect.hpp.08E2F7CD13B78601.idx +0 -0
  10. package/Core/.cache/clangd/index/connection.hpp.849FAEF1523BF2C3.idx +0 -0
  11. package/Core/.cache/clangd/index/display.cpp.F6F6D932BF9F8D8E.idx +0 -0
  12. package/Core/.cache/clangd/index/display.hpp.0C1A9CAD11EE4404.idx +0 -0
  13. package/Core/.cache/clangd/index/filedrop.cpp.669B524B3C501C52.idx +0 -0
  14. package/Core/.cache/clangd/index/filedrop.hpp.48460099C3F35F2D.idx +0 -0
  15. package/Core/.cache/clangd/index/keyboard.cpp.DC6D34E4A4F798DD.idx +0 -0
  16. package/Core/.cache/clangd/index/keyboard.hpp.F016CB68D7DE5A46.idx +0 -0
  17. package/Core/.cache/clangd/index/keyboard_linux.cpp.B403FDCEA7A6CA53.idx +0 -0
  18. package/Core/.cache/clangd/index/menu.cpp.3059F08D8D2DF265.idx +0 -0
  19. package/Core/.cache/clangd/index/menu.hpp.8716DCCC573910D4.idx +0 -0
  20. package/Core/.cache/clangd/index/plusui.hpp.8CFCDFDC2E3F41DD.idx +0 -0
  21. package/Core/.cache/clangd/index/router.cpp.EAC9EAD34C59E573.idx +0 -0
  22. package/Core/.cache/clangd/index/router.hpp.2B06E2EE9998468D.idx +0 -0
  23. package/Core/.cache/clangd/index/stb_image.h.E26CF48FE089A0D3.idx +0 -0
  24. package/Core/.cache/clangd/index/tray.cpp.92F244E7E1D7F0EC.idx +0 -0
  25. package/Core/.cache/clangd/index/tray.hpp.0D881B0601BBBD25.idx +0 -0
  26. package/Core/.cache/clangd/index/webgpu.cpp.FC656FA8BE10FE15.idx +0 -0
  27. package/Core/.cache/clangd/index/webgpu.hpp.5AF1A5E9DF9E5AE0.idx +0 -0
  28. package/Core/.cache/clangd/index/window.cpp.191D8C9ADF874B22.idx +0 -0
  29. package/Core/.cache/clangd/index/window.hpp.B9811B43AA295697.idx +0 -0
  30. package/Core/Features/App/app.cpp +11 -4
  31. package/Core/Features/Tray/tray.cpp +117 -8
  32. package/Core/include/plusui/app.hpp +3 -1
  33. package/package.json +1 -1
@@ -82,6 +82,10 @@ App::Builder &App::Builder::trayTooltip(const std::string &tooltip) {
82
82
  config.trayTooltip = tooltip;
83
83
  return *this;
84
84
  }
85
+ App::Builder &App::Builder::tray(bool enable) {
86
+ config.tray = enable;
87
+ return *this;
88
+ }
85
89
  App::Builder &App::Builder::alwaysOnTop(bool top) {
86
90
  config.alwaysOnTop = top;
87
91
  return *this;
@@ -144,12 +148,15 @@ Window App::Builder::build() {
144
148
  );
145
149
  }
146
150
 
147
- if (!config.trayIconPath.empty()) {
148
- nativeWinPtr->tray().setIcon(config.trayIconPath);
149
- nativeWinPtr->tray().setVisible(true);
151
+ if (config.tray || !config.trayIconPath.empty()) {
152
+ auto& trayMgr = nativeWinPtr->tray();
153
+ if (!config.trayIconPath.empty()) {
154
+ trayMgr.setIcon(config.trayIconPath);
155
+ }
150
156
  if (!config.trayTooltip.empty()) {
151
- nativeWinPtr->tray().setTooltip(config.trayTooltip);
157
+ trayMgr.setTooltip(config.trayTooltip);
152
158
  }
159
+ trayMgr.setVisible(true);
153
160
  }
154
161
 
155
162
  return webviewWin;
@@ -27,7 +27,8 @@
27
27
  #include <stb_image.h>
28
28
 
29
29
  #ifdef __APPLE__
30
- #include <Cocoa/Cocoa.h>
30
+ #import <Cocoa/Cocoa.h>
31
+ #import <AppKit/AppKit.h>
31
32
  #elif !defined(_WIN32)
32
33
  #include <gdk/gdk.h>
33
34
  #include <gtk/gtk.h>
@@ -50,6 +51,12 @@ struct TrayIcon::Impl {
50
51
  #ifdef _WIN32
51
52
  NOTIFYICONDATAW nid = {};
52
53
  HWND hwnd = nullptr;
54
+ #elif defined(__APPLE__)
55
+ NSStatusItem* statusItem = nullptr;
56
+ NSMenu* menu = nullptr;
57
+ #else
58
+ GtkStatusIcon* statusIcon = nullptr;
59
+ GtkMenu* menu = nullptr;
53
60
  #endif
54
61
  };
55
62
 
@@ -69,15 +76,44 @@ TrayIcon TrayIcon::create(const std::string &tooltip,
69
76
  icon.pImpl->nid.uID = 1;
70
77
  icon.pImpl->nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
71
78
  icon.pImpl->nid.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
72
- icon.pImpl->nid.uCallbackMessage = WM_APP + 1; // Example message
79
+ icon.pImpl->nid.uCallbackMessage = WM_APP + 1;
73
80
 
74
81
  if (!tooltip.empty()) {
75
82
  std::wstring wtooltip(tooltip.begin(), tooltip.end());
76
83
  wcsncpy_s(icon.pImpl->nid.szTip, _countof(icon.pImpl->nid.szTip),
77
84
  wtooltip.c_str(), _TRUNCATE);
78
85
  }
79
-
80
- // Note: nim_add should be called after hwnd is set
86
+ #elif defined(__APPLE__)
87
+ icon.pImpl->statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
88
+ if (icon.pImpl->statusItem) {
89
+ if (!iconPath.empty()) {
90
+ NSImage* nsImage = [[NSImage alloc] initWithContentsOfFile:[NSString stringWithUTF8String:iconPath.c_str()]];
91
+ if (nsImage) {
92
+ [nsImage setSize:NSMakeSize(18, 18)];
93
+ icon.pImpl->statusItem.button.image = nsImage;
94
+ }
95
+ }
96
+ if (!tooltip.empty()) {
97
+ icon.pImpl->statusItem.button.toolTip = [NSString stringWithUTF8String:tooltip.c_str()];
98
+ }
99
+ icon.pImpl->menu = [[NSMenu alloc] init];
100
+ icon.pImpl->statusItem.menu = icon.pImpl->menu;
101
+ }
102
+ #else
103
+ icon.pImpl->statusIcon = gtk_status_icon_new();
104
+ if (icon.pImpl->statusIcon) {
105
+ gtk_status_icon_set_title(icon.pImpl->statusIcon, tooltip.empty() ? "PlusUI App" : tooltip.c_str());
106
+ if (!tooltip.empty()) {
107
+ gtk_status_icon_set_tooltip_text(icon.pImpl->statusIcon, tooltip.c_str());
108
+ }
109
+ if (!iconPath.empty()) {
110
+ gtk_status_icon_set_from_file(icon.pImpl->statusIcon, iconPath.c_str());
111
+ } else {
112
+ gtk_status_icon_set_from_icon_name(icon.pImpl->statusIcon, "application-x-executable");
113
+ }
114
+ icon.pImpl->menu = GTK_MENU(gtk_menu_new());
115
+ gtk_status_icon_set_visible(icon.pImpl->statusIcon, TRUE);
116
+ }
81
117
  #endif
82
118
 
83
119
  return icon;
@@ -90,6 +126,14 @@ void TrayIcon::show() {
90
126
  pImpl->nid.hWnd = pImpl->hwnd;
91
127
  Shell_NotifyIconW(NIM_ADD, &pImpl->nid);
92
128
  }
129
+ #elif defined(__APPLE__)
130
+ if (pImpl->statusItem) {
131
+ pImpl->statusItem.button.hidden = NO;
132
+ }
133
+ #else
134
+ if (pImpl->statusIcon) {
135
+ gtk_status_icon_set_visible(pImpl->statusIcon, TRUE);
136
+ }
93
137
  #endif
94
138
  }
95
139
 
@@ -97,6 +141,14 @@ void TrayIcon::hide() {
97
141
  pImpl->visible = false;
98
142
  #ifdef _WIN32
99
143
  Shell_NotifyIconW(NIM_DELETE, &pImpl->nid);
144
+ #elif defined(__APPLE__)
145
+ if (pImpl->statusItem) {
146
+ pImpl->statusItem.button.hidden = YES;
147
+ }
148
+ #else
149
+ if (pImpl->statusIcon) {
150
+ gtk_status_icon_set_visible(pImpl->statusIcon, FALSE);
151
+ }
100
152
  #endif
101
153
  }
102
154
 
@@ -109,6 +161,14 @@ void TrayIcon::setTooltip(const std::string &tooltip) {
109
161
  _TRUNCATE);
110
162
  Shell_NotifyIconW(NIM_MODIFY, &pImpl->nid);
111
163
  }
164
+ #elif defined(__APPLE__)
165
+ if (pImpl->statusItem && !tooltip.empty()) {
166
+ pImpl->statusItem.button.toolTip = [NSString stringWithUTF8String:tooltip.c_str()];
167
+ }
168
+ #else
169
+ if (pImpl->statusIcon && !tooltip.empty()) {
170
+ gtk_status_icon_set_tooltip_text(pImpl->statusIcon, tooltip.c_str());
171
+ }
112
172
  #endif
113
173
  }
114
174
 
@@ -121,6 +181,18 @@ void TrayIcon::setIcon(const std::string &iconPath) {
121
181
  16, LR_LOADFROMFILE);
122
182
  Shell_NotifyIconW(NIM_MODIFY, &pImpl->nid);
123
183
  }
184
+ #elif defined(__APPLE__)
185
+ if (pImpl->statusItem && !iconPath.empty()) {
186
+ NSImage* nsImage = [[NSImage alloc] initWithContentsOfFile:[NSString stringWithUTF8String:iconPath.c_str()]];
187
+ if (nsImage) {
188
+ [nsImage setSize:NSMakeSize(18, 18)];
189
+ pImpl->statusItem.button.image = nsImage;
190
+ }
191
+ }
192
+ #else
193
+ if (pImpl->statusIcon && !iconPath.empty()) {
194
+ gtk_status_icon_set_from_file(pImpl->statusIcon, iconPath.c_str());
195
+ }
124
196
  #endif
125
197
  }
126
198
 
@@ -167,7 +239,6 @@ void TrayIcon::setIconFromMemory(const unsigned char *data, size_t size) {
167
239
  std::vector<uint8_t> pixelVec(pixels, pixels + (width * height * 4));
168
240
 
169
241
  #ifdef _WIN32
170
- // Windows expects BGRA, stb_image returns RGBA
171
242
  for (int i = 0; i < width * height; ++i) {
172
243
  uint8_t r = pixelVec[i * 4 + 0];
173
244
  uint8_t b = pixelVec[i * 4 + 2];
@@ -176,9 +247,33 @@ void TrayIcon::setIconFromMemory(const unsigned char *data, size_t size) {
176
247
  }
177
248
  setIconFromData(pixelVec, width, height);
178
249
  #elif defined(__APPLE__)
179
- // Implementation for macOS (To be implemented)
250
+ if (pImpl->statusItem) {
251
+ NSBitmapImageRep* bitmap = [[NSBitmapImageRep alloc]
252
+ initWithBitmapDataPlanes:&pixels
253
+ pixelsWide:width
254
+ pixelsHigh:height
255
+ bitsPerSample:8
256
+ samplesPerPixel:4
257
+ hasAlpha:YES
258
+ isPlanar:NO
259
+ colorSpaceName:NSCalibratedRGBColorSpace
260
+ bytesPerRow:width * 4
261
+ bitsPerPixel:32];
262
+ NSImage* nsImage = [[NSImage alloc] initWithSize:NSMakeSize(width, height)];
263
+ [nsImage addRepresentation:bitmap];
264
+ [nsImage setSize:NSMakeSize(18, 18)];
265
+ pImpl->statusItem.button.image = nsImage;
266
+ }
180
267
  #else
181
- // Implementation for Linux (GTK) (To be implemented)
268
+ if (pImpl->statusIcon) {
269
+ GdkPixbuf* pixbuf = gdk_pixbuf_new_from_data(
270
+ pixels, GDK_COLORSPACE_RGB, TRUE, 8, width, height,
271
+ width * 4, nullptr, nullptr);
272
+ if (pixbuf) {
273
+ gtk_status_icon_set_from_pixbuf(pImpl->statusIcon, pixbuf);
274
+ g_object_unref(pixbuf);
275
+ }
276
+ }
182
277
  #endif
183
278
 
184
279
  stbi_image_free(pixels);
@@ -233,6 +328,16 @@ void TrayIcon::onMenuItemClick(
233
328
  void TrayIcon::dispose() {
234
329
  #ifdef _WIN32
235
330
  Shell_NotifyIconW(NIM_DELETE, &pImpl->nid);
331
+ #elif defined(__APPLE__)
332
+ if (pImpl->statusItem) {
333
+ [[NSStatusBar systemStatusBar] removeStatusItem:pImpl->statusItem];
334
+ pImpl->statusItem = nil;
335
+ }
336
+ #else
337
+ if (pImpl->statusIcon) {
338
+ gtk_widget_destroy(GTK_WIDGET(pImpl->statusIcon));
339
+ pImpl->statusIcon = nullptr;
340
+ }
236
341
  #endif
237
342
  }
238
343
 
@@ -315,13 +420,17 @@ void TrayManager::setIconFromMemory(const unsigned char *data, size_t size) {
315
420
  if (pImpl->mainIcon) {
316
421
  pImpl->mainIcon->setIconFromMemory(data, size);
317
422
  } else {
318
- // Create the icon if it doesn't exist
319
423
  pImpl->mainIcon = std::make_unique<TrayIcon>(TrayIcon::create("", ""));
320
424
  #ifdef _WIN32
321
425
  pImpl->mainIcon->pImpl->nid.cbSize = sizeof(NOTIFYICONDATAW);
322
426
  pImpl->mainIcon->pImpl->hwnd = pImpl->hwnd;
323
427
  #endif
428
+ pImpl->icons.push_back(pImpl->mainIcon.get());
429
+ if (pImpl->onCreatedCallback) {
430
+ pImpl->onCreatedCallback(*pImpl->mainIcon);
431
+ }
324
432
  pImpl->mainIcon->setIconFromMemory(data, size);
433
+ pImpl->mainIcon->show();
325
434
  }
326
435
  }
327
436
 
@@ -35,13 +35,14 @@ public:
35
35
  bool devtools = true;
36
36
  std::string trayIconPath;
37
37
  std::string trayTooltip;
38
+ bool tray = false;
38
39
  bool alwaysOnTop = false;
39
40
  bool centered = true;
40
41
  bool transparent = false;
41
42
  bool decorations = true;
42
43
  bool skipTaskbar = false;
43
44
  bool scrollbars = true;
44
- bool fileDrop = true; // Enable OS file drop
45
+ bool fileDrop = true;
45
46
  };
46
47
 
47
48
  Builder();
@@ -53,6 +54,7 @@ public:
53
54
  Builder &devtools(bool d);
54
55
  Builder &trayIcon(const std::string &icon);
55
56
  Builder &trayTooltip(const std::string &tooltip);
57
+ Builder &tray(bool enable);
56
58
  Builder &alwaysOnTop(bool top);
57
59
  Builder &centered(bool center);
58
60
  Builder &transparent(bool transparent);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plusui-native-core",
3
- "version": "0.1.106",
3
+ "version": "0.1.107",
4
4
  "description": "PlusUI Core framework (frontend + backend implementations)",
5
5
  "type": "module",
6
6
  "main": "./Core/Features/API/index.ts",