plusui-native-core 0.1.3 → 0.1.5
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.
- package/Core/CMakeLists.txt +190 -7
- package/Core/Features/App/app.cpp +129 -0
- package/Core/Features/App/app.ts +126 -0
- package/Core/Features/Browser/browser.cpp +181 -0
- package/Core/Features/Browser/browser.ts +182 -0
- package/Core/Features/Clipboard/clipboard.cpp +234 -0
- package/Core/Features/Clipboard/clipboard.ts +113 -0
- package/Core/Features/Display/display.cpp +209 -0
- package/Core/Features/Display/display.ts +104 -0
- package/Core/Features/Event/Events.ts +166 -0
- package/Core/Features/Event/events.cpp +200 -0
- package/Core/Features/Keyboard/keyboard.cpp +186 -0
- package/Core/Features/Keyboard/keyboard.ts +175 -0
- package/Core/Features/Menu/context-menu.css +293 -0
- package/Core/Features/Menu/menu.cpp +481 -0
- package/Core/Features/Menu/menu.ts +439 -0
- package/Core/Features/Tray/tray.cpp +310 -0
- package/Core/Features/Tray/tray.ts +68 -0
- package/Core/Features/WebGPU/webgpu.cpp +937 -0
- package/Core/Features/WebGPU/webgpu.ts +1013 -0
- package/Core/Features/WebView/webview.cpp +1052 -0
- package/Core/Features/WebView/webview.ts +510 -0
- package/Core/Features/Window/window.cpp +664 -0
- package/Core/Features/Window/window.ts +142 -0
- package/Core/Features/WindowManager/window_manager.cpp +341 -0
- package/Core/include/plusui/app.hpp +73 -0
- package/Core/include/plusui/browser.hpp +66 -0
- package/Core/include/plusui/clipboard.hpp +41 -0
- package/Core/include/plusui/events.hpp +58 -0
- package/Core/include/{keyboard.hpp → plusui/keyboard.hpp} +21 -44
- package/Core/include/plusui/menu.hpp +153 -0
- package/Core/include/plusui/tray.hpp +93 -0
- package/Core/include/plusui/webgpu.hpp +434 -0
- package/Core/include/plusui/webview.hpp +142 -0
- package/Core/include/plusui/window.hpp +111 -0
- package/Core/include/plusui/window_manager.hpp +57 -0
- package/Core/vendor/WebView2EnvironmentOptions.h +406 -0
- package/Core/vendor/stb_image.h +7988 -0
- package/Core/vendor/webview.h +618 -510
- package/Core/vendor/webview2.h +52079 -0
- package/README.md +19 -0
- package/package.json +12 -15
- package/Core/include/app.hpp +0 -121
- package/Core/include/menu.hpp +0 -79
- package/Core/include/tray.hpp +0 -81
- package/Core/include/window.hpp +0 -106
- package/Core/src/app.cpp +0 -311
- package/Core/src/display.cpp +0 -424
- package/Core/src/tray.cpp +0 -275
- package/Core/src/window.cpp +0 -528
- package/dist/index.d.ts +0 -205
- package/dist/index.js +0 -198
- package/src/index.ts +0 -574
- /package/Core/include/{display.hpp → plusui/display.hpp} +0 -0
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
#ifdef _WIN32
|
|
2
|
+
#ifndef _WIN32_WINNT
|
|
3
|
+
#define _WIN32_WINNT 0x0601
|
|
4
|
+
#endif
|
|
5
|
+
#include <windows.h>
|
|
6
|
+
|
|
7
|
+
#ifndef EXTERN_C
|
|
8
|
+
#ifdef __cplusplus
|
|
9
|
+
#define EXTERN_C extern "C"
|
|
10
|
+
#else
|
|
11
|
+
#define EXTERN_C extern
|
|
12
|
+
#endif
|
|
13
|
+
#endif
|
|
14
|
+
|
|
15
|
+
#include <shellapi.h>
|
|
16
|
+
#include <shlobj.h>
|
|
17
|
+
#pragma comment(lib, "shell32.lib")
|
|
18
|
+
#endif
|
|
19
|
+
|
|
20
|
+
#include <algorithm>
|
|
21
|
+
#include <iostream>
|
|
22
|
+
#include <plusui/tray.hpp>
|
|
23
|
+
#include <string>
|
|
24
|
+
#include <vector>
|
|
25
|
+
|
|
26
|
+
#define STB_IMAGE_IMPLEMENTATION
|
|
27
|
+
#include <stb_image.h>
|
|
28
|
+
|
|
29
|
+
#ifdef __APPLE__
|
|
30
|
+
#include <Cocoa/Cocoa.h>
|
|
31
|
+
#elif !defined(_WIN32)
|
|
32
|
+
#include <gdk/gdk.h>
|
|
33
|
+
#include <gtk/gtk.h>
|
|
34
|
+
#endif
|
|
35
|
+
|
|
36
|
+
namespace plusui {
|
|
37
|
+
|
|
38
|
+
struct TrayIcon::Impl {
|
|
39
|
+
int id = 0;
|
|
40
|
+
std::string tooltip;
|
|
41
|
+
std::string iconPath;
|
|
42
|
+
bool visible = true;
|
|
43
|
+
|
|
44
|
+
std::function<void(int, int)> clickCallback;
|
|
45
|
+
std::function<void(int, int)> rightClickCallback;
|
|
46
|
+
std::function<void()> doubleClickCallback;
|
|
47
|
+
std::function<void(const std::string &)> menuItemCallback;
|
|
48
|
+
std::vector<TrayMenuItem> menuItems;
|
|
49
|
+
|
|
50
|
+
#ifdef _WIN32
|
|
51
|
+
NOTIFYICONDATAW nid = {};
|
|
52
|
+
HWND hwnd = nullptr;
|
|
53
|
+
#endif
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
TrayIcon::TrayIcon() : pImpl(std::make_unique<Impl>()) {}
|
|
57
|
+
TrayIcon::~TrayIcon() { dispose(); }
|
|
58
|
+
|
|
59
|
+
TrayIcon::TrayIcon(TrayIcon &&other) noexcept = default;
|
|
60
|
+
TrayIcon &TrayIcon::operator=(TrayIcon &&other) noexcept = default;
|
|
61
|
+
|
|
62
|
+
TrayIcon TrayIcon::create(const std::string &tooltip,
|
|
63
|
+
const std::string &iconPath) {
|
|
64
|
+
TrayIcon icon;
|
|
65
|
+
icon.pImpl->tooltip = tooltip;
|
|
66
|
+
icon.pImpl->iconPath = iconPath;
|
|
67
|
+
|
|
68
|
+
#ifdef _WIN32
|
|
69
|
+
icon.pImpl->nid.uID = 1;
|
|
70
|
+
icon.pImpl->nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
|
|
71
|
+
icon.pImpl->nid.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
|
|
72
|
+
icon.pImpl->nid.uCallbackMessage = WM_APP + 1; // Example message
|
|
73
|
+
|
|
74
|
+
if (!tooltip.empty()) {
|
|
75
|
+
std::wstring wtooltip(tooltip.begin(), tooltip.end());
|
|
76
|
+
wcsncpy_s(icon.pImpl->nid.szTip, _countof(icon.pImpl->nid.szTip),
|
|
77
|
+
wtooltip.c_str(), _TRUNCATE);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Note: nim_add should be called after hwnd is set
|
|
81
|
+
#endif
|
|
82
|
+
|
|
83
|
+
return icon;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
void TrayIcon::show() {
|
|
87
|
+
pImpl->visible = true;
|
|
88
|
+
#ifdef _WIN32
|
|
89
|
+
if (pImpl->hwnd) {
|
|
90
|
+
pImpl->nid.hWnd = pImpl->hwnd;
|
|
91
|
+
Shell_NotifyIconW(NIM_ADD, &pImpl->nid);
|
|
92
|
+
}
|
|
93
|
+
#endif
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
void TrayIcon::hide() {
|
|
97
|
+
pImpl->visible = false;
|
|
98
|
+
#ifdef _WIN32
|
|
99
|
+
Shell_NotifyIconW(NIM_DELETE, &pImpl->nid);
|
|
100
|
+
#endif
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
void TrayIcon::setTooltip(const std::string &tooltip) {
|
|
104
|
+
pImpl->tooltip = tooltip;
|
|
105
|
+
#ifdef _WIN32
|
|
106
|
+
if (!tooltip.empty()) {
|
|
107
|
+
std::wstring wtooltip(tooltip.begin(), tooltip.end());
|
|
108
|
+
wcsncpy_s(pImpl->nid.szTip, _countof(pImpl->nid.szTip), wtooltip.c_str(),
|
|
109
|
+
_TRUNCATE);
|
|
110
|
+
Shell_NotifyIconW(NIM_MODIFY, &pImpl->nid);
|
|
111
|
+
}
|
|
112
|
+
#endif
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
void TrayIcon::setIcon(const std::string &iconPath) {
|
|
116
|
+
pImpl->iconPath = iconPath;
|
|
117
|
+
#ifdef _WIN32
|
|
118
|
+
if (!iconPath.empty()) {
|
|
119
|
+
std::wstring wpath(iconPath.begin(), iconPath.end());
|
|
120
|
+
pImpl->nid.hIcon = (HICON)LoadImageW(nullptr, wpath.c_str(), IMAGE_ICON, 16,
|
|
121
|
+
16, LR_LOADFROMFILE);
|
|
122
|
+
Shell_NotifyIconW(NIM_MODIFY, &pImpl->nid);
|
|
123
|
+
}
|
|
124
|
+
#endif
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
void TrayIcon::setIconFromData(const std::vector<uint8_t> &data, int width,
|
|
128
|
+
int height) {
|
|
129
|
+
#ifdef _WIN32
|
|
130
|
+
if (!data.empty()) {
|
|
131
|
+
BITMAPINFO bmi = {};
|
|
132
|
+
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
133
|
+
bmi.bmiHeader.biWidth = width;
|
|
134
|
+
bmi.bmiHeader.biHeight = -height;
|
|
135
|
+
bmi.bmiHeader.biPlanes = 1;
|
|
136
|
+
bmi.bmiHeader.biBitCount = 32;
|
|
137
|
+
bmi.bmiHeader.biCompression = BI_RGB;
|
|
138
|
+
|
|
139
|
+
void *bits = nullptr;
|
|
140
|
+
HBITMAP hbm =
|
|
141
|
+
CreateDIBSection(nullptr, &bmi, DIB_RGB_COLORS, &bits, nullptr, 0);
|
|
142
|
+
if (hbm && bits && data.size() >= (size_t)width * height * 4) {
|
|
143
|
+
memcpy(bits, data.data(), width * height * 4);
|
|
144
|
+
|
|
145
|
+
ICONINFO ii = {};
|
|
146
|
+
ii.fIcon = TRUE;
|
|
147
|
+
ii.hbmColor = hbm;
|
|
148
|
+
ii.hbmMask = hbm;
|
|
149
|
+
|
|
150
|
+
HICON hIcon = CreateIconIndirect(&ii);
|
|
151
|
+
if (hIcon) {
|
|
152
|
+
pImpl->nid.hIcon = hIcon;
|
|
153
|
+
Shell_NotifyIconW(NIM_MODIFY, &pImpl->nid);
|
|
154
|
+
DestroyIcon(hIcon);
|
|
155
|
+
}
|
|
156
|
+
DeleteObject(hbm);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
#endif
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
void TrayIcon::setIconFromMemory(const unsigned char *data, size_t size) {
|
|
163
|
+
int width, height, channels;
|
|
164
|
+
unsigned char *pixels =
|
|
165
|
+
stbi_load_from_memory(data, (int)size, &width, &height, &channels, 4);
|
|
166
|
+
if (pixels) {
|
|
167
|
+
std::vector<uint8_t> pixelVec(pixels, pixels + (width * height * 4));
|
|
168
|
+
|
|
169
|
+
#ifdef _WIN32
|
|
170
|
+
// Windows expects BGRA, stb_image returns RGBA
|
|
171
|
+
for (int i = 0; i < width * height; ++i) {
|
|
172
|
+
uint8_t r = pixelVec[i * 4 + 0];
|
|
173
|
+
uint8_t b = pixelVec[i * 4 + 2];
|
|
174
|
+
pixelVec[i * 4 + 0] = b;
|
|
175
|
+
pixelVec[i * 4 + 2] = r;
|
|
176
|
+
}
|
|
177
|
+
setIconFromData(pixelVec, width, height);
|
|
178
|
+
#elif defined(__APPLE__)
|
|
179
|
+
// Implementation for macOS (To be implemented)
|
|
180
|
+
#else
|
|
181
|
+
// Implementation for Linux (GTK) (To be implemented)
|
|
182
|
+
#endif
|
|
183
|
+
|
|
184
|
+
stbi_image_free(pixels);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Methods removed: show, hide (duplicate definitions)
|
|
189
|
+
|
|
190
|
+
bool TrayIcon::isVisible() const { return pImpl->visible; }
|
|
191
|
+
|
|
192
|
+
void TrayIcon::setMenu(const std::vector<TrayMenuItem> &items) {
|
|
193
|
+
pImpl->menuItems = items;
|
|
194
|
+
#ifdef _WIN32
|
|
195
|
+
HMENU hMenu = CreatePopupMenu();
|
|
196
|
+
for (const auto &item : items) {
|
|
197
|
+
if (item.separator) {
|
|
198
|
+
AppendMenuW(hMenu, MF_SEPARATOR, 0, nullptr);
|
|
199
|
+
} else {
|
|
200
|
+
std::wstring label(item.label.begin(), item.label.end());
|
|
201
|
+
UINT flags = MF_STRING;
|
|
202
|
+
if (!item.enabled)
|
|
203
|
+
flags |= MF_DISABLED;
|
|
204
|
+
if (item.checked)
|
|
205
|
+
flags |= MF_CHECKED;
|
|
206
|
+
AppendMenuW(hMenu, flags, (UINT_PTR)item.id.c_str(), label.c_str());
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
#endif
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
void TrayIcon::setContextMenu(const std::vector<TrayMenuItem> &items) {
|
|
213
|
+
setMenu(items);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
void TrayIcon::onClick(std::function<void(int, int)> callback) {
|
|
217
|
+
pImpl->clickCallback = callback;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
void TrayIcon::onRightClick(std::function<void(int, int)> callback) {
|
|
221
|
+
pImpl->rightClickCallback = callback;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
void TrayIcon::onDoubleClick(std::function<void()> callback) {
|
|
225
|
+
pImpl->doubleClickCallback = callback;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
void TrayIcon::onMenuItemClick(
|
|
229
|
+
std::function<void(const std::string &)> callback) {
|
|
230
|
+
pImpl->menuItemCallback = callback;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
void TrayIcon::dispose() {
|
|
234
|
+
#ifdef _WIN32
|
|
235
|
+
Shell_NotifyIconW(NIM_DELETE, &pImpl->nid);
|
|
236
|
+
#endif
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
struct TrayManager::Impl {
|
|
240
|
+
HWND hwnd = nullptr;
|
|
241
|
+
std::unique_ptr<TrayIcon> mainIcon;
|
|
242
|
+
std::vector<TrayIcon *> icons;
|
|
243
|
+
std::function<void(TrayIcon &)> onCreatedCallback;
|
|
244
|
+
std::function<void(int)> onDestroyedCallback;
|
|
245
|
+
std::string currentIconPath;
|
|
246
|
+
std::string currentTooltip;
|
|
247
|
+
bool currentVisible = false;
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
TrayManager::TrayManager() : pImpl(std::make_unique<Impl>()) {}
|
|
251
|
+
TrayManager::~TrayManager() = default;
|
|
252
|
+
|
|
253
|
+
TrayManager &TrayManager::instance() {
|
|
254
|
+
static TrayManager inst;
|
|
255
|
+
return inst;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
void TrayManager::setWindowHandle(void *hwnd) {
|
|
259
|
+
#ifdef _WIN32
|
|
260
|
+
pImpl->hwnd = (HWND)hwnd;
|
|
261
|
+
if (pImpl->mainIcon) {
|
|
262
|
+
pImpl->mainIcon->pImpl->hwnd = pImpl->hwnd;
|
|
263
|
+
}
|
|
264
|
+
#endif
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
void TrayManager::setIcon(const std::string &iconPath) {
|
|
268
|
+
pImpl->currentIconPath = iconPath;
|
|
269
|
+
if (pImpl->mainIcon) {
|
|
270
|
+
pImpl->mainIcon->setIcon(iconPath);
|
|
271
|
+
} else {
|
|
272
|
+
pImpl->mainIcon =
|
|
273
|
+
std::make_unique<TrayIcon>(TrayIcon::create("", iconPath));
|
|
274
|
+
#ifdef _WIN32
|
|
275
|
+
pImpl->mainIcon->pImpl->nid.cbSize = sizeof(NOTIFYICONDATAW);
|
|
276
|
+
pImpl->mainIcon->pImpl->hwnd = pImpl->hwnd;
|
|
277
|
+
#endif
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
void TrayManager::setTooltip(const std::string &tooltip) {
|
|
282
|
+
pImpl->currentTooltip = tooltip;
|
|
283
|
+
if (pImpl->mainIcon) {
|
|
284
|
+
pImpl->mainIcon->setTooltip(tooltip);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
void TrayManager::setVisible(bool visible) {
|
|
289
|
+
pImpl->currentVisible = visible;
|
|
290
|
+
if (pImpl->mainIcon) {
|
|
291
|
+
if (visible)
|
|
292
|
+
pImpl->mainIcon->show();
|
|
293
|
+
else
|
|
294
|
+
pImpl->mainIcon->hide();
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
std::vector<TrayIcon *> TrayManager::getIcons() { return pImpl->icons; }
|
|
299
|
+
|
|
300
|
+
void TrayManager::onTrayCreated(std::function<void(TrayIcon &)> callback) {
|
|
301
|
+
pImpl->onCreatedCallback = callback;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
void TrayManager::onTrayDestroyed(std::function<void(int)> callback) {
|
|
305
|
+
pImpl->onDestroyedCallback = callback;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
void TrayManager::refresh() {}
|
|
309
|
+
|
|
310
|
+
} // namespace plusui
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export interface TrayMenuItem {
|
|
2
|
+
id: string;
|
|
3
|
+
label: string;
|
|
4
|
+
icon?: string;
|
|
5
|
+
enabled?: boolean;
|
|
6
|
+
checked?: boolean;
|
|
7
|
+
separator?: boolean;
|
|
8
|
+
submenu?: TrayMenuItem[];
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface TrayIconData {
|
|
12
|
+
id: number;
|
|
13
|
+
tooltip: string;
|
|
14
|
+
iconPath: string;
|
|
15
|
+
isVisible: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class TrayAPI {
|
|
19
|
+
constructor(
|
|
20
|
+
private invokeFn: (name: string, args?: unknown[]) => Promise<unknown>,
|
|
21
|
+
private eventFn: (event: string, callback: (...args: unknown[]) => void) => () => void
|
|
22
|
+
) {}
|
|
23
|
+
|
|
24
|
+
async setIcon(iconPath: string): Promise<void> {
|
|
25
|
+
await this.invokeFn('tray.setIcon', [iconPath]);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async setTooltip(tooltip: string): Promise<void> {
|
|
29
|
+
await this.invokeFn('tray.setTooltip', [tooltip]);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async setVisible(visible: boolean): Promise<void> {
|
|
33
|
+
await this.invokeFn('tray.setVisible', [visible]);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async setMenu(items: TrayMenuItem[]): Promise<void> {
|
|
37
|
+
await this.invokeFn('tray.setMenu', [items]);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async setContextMenu(items: TrayMenuItem[]): Promise<void> {
|
|
41
|
+
await this.invokeFn('tray.setContextMenu', [items]);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
onClick(callback: (x: number, y: number) => void): () => void {
|
|
45
|
+
return this.eventFn('tray:click', callback as (...args: unknown[]) => void);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
onDoubleClick(callback: () => void): () => void {
|
|
49
|
+
return this.eventFn('tray:doubleClick', callback as (...args: unknown[]) => void);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
onRightClick(callback: (x: number, y: number) => void): () => void {
|
|
53
|
+
return this.eventFn('tray:rightClick', callback as (...args: unknown[]) => void);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
onMenuItemClick(callback: (id: string) => void): () => void {
|
|
57
|
+
return this.eventFn('tray:menuItemClick', callback as (...args: unknown[]) => void);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function createTrayAPI(
|
|
62
|
+
invokeFn: (name: string, args?: unknown[]) => Promise<unknown>,
|
|
63
|
+
eventFn: (event: string, callback: (...args: unknown[]) => void) => () => void
|
|
64
|
+
): TrayAPI {
|
|
65
|
+
return new TrayAPI(invokeFn, eventFn);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export default TrayAPI;
|