plusui-native-core 0.1.4 → 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.
Files changed (54) hide show
  1. package/Core/CMakeLists.txt +190 -7
  2. package/Core/Features/App/app.cpp +129 -0
  3. package/Core/Features/App/app.ts +126 -0
  4. package/Core/Features/Browser/browser.cpp +181 -0
  5. package/Core/Features/Browser/browser.ts +182 -0
  6. package/Core/Features/Clipboard/clipboard.cpp +234 -0
  7. package/Core/Features/Clipboard/clipboard.ts +113 -0
  8. package/Core/Features/Display/display.cpp +209 -0
  9. package/Core/Features/Display/display.ts +104 -0
  10. package/Core/Features/Event/Events.ts +166 -0
  11. package/Core/Features/Event/events.cpp +200 -0
  12. package/Core/Features/Keyboard/keyboard.cpp +186 -0
  13. package/Core/Features/Keyboard/keyboard.ts +175 -0
  14. package/Core/Features/Menu/context-menu.css +293 -0
  15. package/Core/Features/Menu/menu.cpp +481 -0
  16. package/Core/Features/Menu/menu.ts +439 -0
  17. package/Core/Features/Tray/tray.cpp +310 -0
  18. package/Core/Features/Tray/tray.ts +68 -0
  19. package/Core/Features/WebGPU/webgpu.cpp +937 -0
  20. package/Core/Features/WebGPU/webgpu.ts +1013 -0
  21. package/Core/Features/WebView/webview.cpp +1052 -0
  22. package/Core/Features/WebView/webview.ts +510 -0
  23. package/Core/Features/Window/window.cpp +664 -0
  24. package/Core/Features/Window/window.ts +142 -0
  25. package/Core/Features/WindowManager/window_manager.cpp +341 -0
  26. package/Core/include/plusui/app.hpp +73 -0
  27. package/Core/include/plusui/browser.hpp +66 -0
  28. package/Core/include/plusui/clipboard.hpp +41 -0
  29. package/Core/include/plusui/events.hpp +58 -0
  30. package/Core/include/{keyboard.hpp → plusui/keyboard.hpp} +21 -44
  31. package/Core/include/plusui/menu.hpp +153 -0
  32. package/Core/include/plusui/tray.hpp +93 -0
  33. package/Core/include/plusui/webgpu.hpp +434 -0
  34. package/Core/include/plusui/webview.hpp +142 -0
  35. package/Core/include/plusui/window.hpp +111 -0
  36. package/Core/include/plusui/window_manager.hpp +57 -0
  37. package/Core/vendor/WebView2EnvironmentOptions.h +406 -0
  38. package/Core/vendor/stb_image.h +7988 -0
  39. package/Core/vendor/webview.h +618 -510
  40. package/Core/vendor/webview2.h +52079 -0
  41. package/README.md +19 -0
  42. package/package.json +12 -15
  43. package/Core/include/app.hpp +0 -121
  44. package/Core/include/menu.hpp +0 -79
  45. package/Core/include/tray.hpp +0 -81
  46. package/Core/include/window.hpp +0 -106
  47. package/Core/src/app.cpp +0 -311
  48. package/Core/src/display.cpp +0 -424
  49. package/Core/src/tray.cpp +0 -275
  50. package/Core/src/window.cpp +0 -528
  51. package/dist/index.d.ts +0 -205
  52. package/dist/index.js +0 -198
  53. package/src/index.ts +0 -574
  54. /package/Core/include/{display.hpp → plusui/display.hpp} +0 -0
@@ -0,0 +1,142 @@
1
+ export interface WindowSize {
2
+ width: number;
3
+ height: number;
4
+ }
5
+
6
+ export interface WindowPosition {
7
+ x: number;
8
+ y: number;
9
+ }
10
+
11
+ export interface WindowRect {
12
+ x: number;
13
+ y: number;
14
+ width: number;
15
+ height: number;
16
+ }
17
+
18
+ export interface WindowState {
19
+ isMinimized: boolean;
20
+ isMaximized: boolean;
21
+ isVisible: boolean;
22
+ isFullscreen: boolean;
23
+ }
24
+
25
+ export type WindowId = string;
26
+
27
+ let _invoke: ((method: string, args?: unknown[]) => Promise<unknown>) | null = null;
28
+
29
+ export function setInvokeFn(fn: (method: string, args?: unknown[]) => Promise<unknown>) {
30
+ _invoke = fn;
31
+ }
32
+
33
+ async function invoke(method: string, args?: unknown[]): Promise<unknown> {
34
+ if (!_invoke) {
35
+ if (typeof window !== 'undefined' && (window as any).__invoke__) {
36
+ _invoke = (window as any).__invoke__;
37
+ } else {
38
+ throw new Error('Window API not initialized');
39
+ }
40
+ }
41
+ return _invoke(method, args);
42
+ }
43
+
44
+ export const window = {
45
+ async minimize(id?: WindowId): Promise<void> {
46
+ await invoke('window.minimize', id ? [id] : []);
47
+ },
48
+
49
+ async maximize(id?: WindowId): Promise<void> {
50
+ await invoke('window.maximize', id ? [id] : []);
51
+ },
52
+
53
+ async restore(id?: WindowId): Promise<void> {
54
+ await invoke('window.restore', id ? [id] : []);
55
+ },
56
+
57
+ async close(id?: WindowId): Promise<void> {
58
+ await invoke('window.close', id ? [id] : []);
59
+ },
60
+
61
+ async show(id?: WindowId): Promise<void> {
62
+ await invoke('window.show', id ? [id] : []);
63
+ },
64
+
65
+ async hide(id?: WindowId): Promise<void> {
66
+ await invoke('window.hide', id ? [id] : []);
67
+ },
68
+
69
+ async center(id?: WindowId): Promise<void> {
70
+ await invoke('window.center', id ? [id] : []);
71
+ },
72
+
73
+ async setSize(width: number, height: number, id?: WindowId): Promise<void> {
74
+ const args = id ? [width, height, id] : [width, height];
75
+ await invoke('window.setSize', args);
76
+ },
77
+
78
+ async setPosition(x: number, y: number, id?: WindowId): Promise<void> {
79
+ const args = id ? [x, y, id] : [x, y];
80
+ await invoke('window.setPosition', args);
81
+ },
82
+
83
+ async setTitle(title: string, id?: WindowId): Promise<void> {
84
+ const args = id ? [title, id] : [title];
85
+ await invoke('window.setTitle', args);
86
+ },
87
+
88
+ async setFullscreen(enabled: boolean, id?: WindowId): Promise<void> {
89
+ const args = id ? [enabled, id] : [enabled];
90
+ await invoke('window.setFullscreen', args);
91
+ },
92
+
93
+ async setAlwaysOnTop(enabled: boolean, id?: WindowId): Promise<void> {
94
+ const args = id ? [enabled, id] : [enabled];
95
+ await invoke('window.setAlwaysOnTop', args);
96
+ },
97
+
98
+ async setResizable(enabled: boolean, id?: WindowId): Promise<void> {
99
+ const args = id ? [enabled, id] : [enabled];
100
+ await invoke('window.setResizable', args);
101
+ },
102
+
103
+ async setDecorations(enabled: boolean, id?: WindowId): Promise<void> {
104
+ const args = id ? [enabled, id] : [enabled];
105
+ await invoke('window.setDecorations', args);
106
+ },
107
+
108
+ async setTransparency(alpha: number, id?: WindowId): Promise<void> {
109
+ const args = id ? [alpha, id] : [alpha];
110
+ await invoke('window.setTransparency', args);
111
+ },
112
+
113
+ async getSize(id?: WindowId): Promise<WindowSize> {
114
+ return await invoke('window.getSize', id ? [id] : []) as Promise<WindowSize>;
115
+ },
116
+
117
+ async getPosition(id?: WindowId): Promise<WindowPosition> {
118
+ return await invoke('window.getPosition', id ? [id] : []) as Promise<WindowPosition>;
119
+ },
120
+
121
+ async getRect(id?: WindowId): Promise<WindowRect> {
122
+ return await invoke('window.getRect', id ? [id] : []) as Promise<WindowRect>;
123
+ },
124
+
125
+ async getState(id?: WindowId): Promise<WindowState> {
126
+ return await invoke('window.getState', id ? [id] : []) as Promise<WindowState>;
127
+ },
128
+
129
+ async isMaximized(id?: WindowId): Promise<boolean> {
130
+ return await invoke('window.isMaximized', id ? [id] : []) as Promise<boolean>;
131
+ },
132
+
133
+ async isMinimized(id?: WindowId): Promise<boolean> {
134
+ return await invoke('window.isMinimized', id ? [id] : []) as Promise<boolean>;
135
+ },
136
+
137
+ async isVisible(id?: WindowId): Promise<boolean> {
138
+ return await invoke('window.isVisible', id ? [id] : []) as Promise<boolean>;
139
+ }
140
+ };
141
+
142
+ export default window;
@@ -0,0 +1,341 @@
1
+ #include <plusui/window_manager.hpp>
2
+
3
+ #ifdef _WIN32
4
+ #include <windows.h>
5
+ #elif defined(__APPLE__)
6
+ #include <Cocoa/Cocoa.h>
7
+ #else
8
+ #include <gtk/gtk.h>
9
+ #endif
10
+
11
+ namespace plusui {
12
+
13
+ struct WindowManager::Impl {
14
+ void *nativeWindow = nullptr;
15
+ bool visible = true;
16
+ bool maximized = false;
17
+ bool minimized = false;
18
+
19
+ #ifdef _WIN32
20
+ HWND hwnd() const { return (HWND)nativeWindow; }
21
+ #endif
22
+ };
23
+
24
+ WindowManager::WindowManager() : pImpl(std::make_unique<Impl>()) {}
25
+
26
+ WindowManager::WindowManager(void *nativeWindow)
27
+ : pImpl(std::make_unique<Impl>()) {
28
+ pImpl->nativeWindow = nativeWindow;
29
+ }
30
+
31
+ WindowManager::~WindowManager() = default;
32
+
33
+ void WindowManager::setTitle(const std::string &title) {
34
+ #ifdef _WIN32
35
+ if (pImpl->nativeWindow) {
36
+ std::wstring wideTitle(title.begin(), title.end());
37
+ SetWindowTextW(pImpl->hwnd(), wideTitle.c_str());
38
+ }
39
+ #elif defined(__APPLE__)
40
+ // macOS implementation
41
+ #else
42
+ if (pImpl->nativeWindow) {
43
+ gtk_window_set_title(GTK_WINDOW(pImpl->nativeWindow), title.c_str());
44
+ }
45
+ #endif
46
+ }
47
+
48
+ void WindowManager::setSize(int width, int height) {
49
+ #ifdef _WIN32
50
+ if (pImpl->nativeWindow) {
51
+ SetWindowPos(pImpl->hwnd(), nullptr, 0, 0, width, height,
52
+ SWP_NOMOVE | SWP_NOZORDER);
53
+ }
54
+ #elif defined(__APPLE__)
55
+ // macOS implementation
56
+ #else
57
+ if (pImpl->nativeWindow) {
58
+ gtk_window_resize(GTK_WINDOW(pImpl->nativeWindow), width, height);
59
+ }
60
+ #endif
61
+ }
62
+
63
+ WindowSize WindowManager::getSize() const {
64
+ WindowSize size;
65
+ #ifdef _WIN32
66
+ if (pImpl->nativeWindow) {
67
+ RECT rc;
68
+ GetWindowRect(pImpl->hwnd(), &rc);
69
+ size.width = rc.right - rc.left;
70
+ size.height = rc.bottom - rc.top;
71
+ }
72
+ #elif defined(__APPLE__)
73
+ // macOS implementation
74
+ #else
75
+ if (pImpl->nativeWindow) {
76
+ gint w, h;
77
+ gtk_window_get_size(GTK_WINDOW(pImpl->nativeWindow), &w, &h);
78
+ size.width = w;
79
+ size.height = h;
80
+ }
81
+ #endif
82
+ return size;
83
+ }
84
+
85
+ void WindowManager::setPosition(int x, int y) {
86
+ #ifdef _WIN32
87
+ if (pImpl->nativeWindow) {
88
+ SetWindowPos(pImpl->hwnd(), nullptr, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
89
+ }
90
+ #elif defined(__APPLE__)
91
+ // macOS implementation
92
+ #else
93
+ if (pImpl->nativeWindow) {
94
+ gtk_window_move(GTK_WINDOW(pImpl->nativeWindow), x, y);
95
+ }
96
+ #endif
97
+ }
98
+
99
+ WindowPosition WindowManager::getPosition() const {
100
+ WindowPosition pos;
101
+ #ifdef _WIN32
102
+ if (pImpl->nativeWindow) {
103
+ RECT rc;
104
+ GetWindowRect(pImpl->hwnd(), &rc);
105
+ pos.x = rc.left;
106
+ pos.y = rc.top;
107
+ }
108
+ #elif defined(__APPLE__)
109
+ // macOS implementation
110
+ #else
111
+ if (pImpl->nativeWindow) {
112
+ gint x, y;
113
+ gtk_window_get_position(GTK_WINDOW(pImpl->nativeWindow), &x, &y);
114
+ pos.x = x;
115
+ pos.y = y;
116
+ }
117
+ #endif
118
+ return pos;
119
+ }
120
+
121
+ void WindowManager::setCenter() {
122
+ #ifdef _WIN32
123
+ if (pImpl->nativeWindow) {
124
+ RECT rc, screen;
125
+ GetWindowRect(pImpl->hwnd(), &rc);
126
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &screen, 0);
127
+ int x = (screen.right - (rc.right - rc.left)) / 2;
128
+ int y = (screen.bottom - (rc.bottom - rc.top)) / 2;
129
+ SetWindowPos(pImpl->hwnd(), nullptr, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
130
+ }
131
+ #elif defined(__APPLE__)
132
+ // macOS implementation
133
+ #else
134
+ if (pImpl->nativeWindow) {
135
+ gtk_window_set_position(GTK_WINDOW(pImpl->nativeWindow),
136
+ GTK_WIN_POS_CENTER);
137
+ }
138
+ #endif
139
+ }
140
+
141
+ void WindowManager::setFullscreen(bool enabled) {
142
+ #ifdef _WIN32
143
+ if (pImpl->nativeWindow) {
144
+ if (enabled) {
145
+ ShowWindow(pImpl->hwnd(), SW_MAXIMIZE);
146
+ } else {
147
+ ShowWindow(pImpl->hwnd(), SW_RESTORE);
148
+ }
149
+ }
150
+ #elif defined(__APPLE__)
151
+ // macOS implementation
152
+ #else
153
+ if (pImpl->nativeWindow) {
154
+ if (enabled) {
155
+ gtk_window_fullscreen(GTK_WINDOW(pImpl->nativeWindow));
156
+ } else {
157
+ gtk_window_unfullscreen(GTK_WINDOW(pImpl->nativeWindow));
158
+ }
159
+ }
160
+ #endif
161
+ }
162
+
163
+ void WindowManager::setAlwaysOnTop(bool enabled) {
164
+ #ifdef _WIN32
165
+ if (pImpl->nativeWindow) {
166
+ SetWindowPos(pImpl->hwnd(), enabled ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0,
167
+ 0, 0, SWP_NOMOVE | SWP_NOSIZE);
168
+ }
169
+ #elif defined(__APPLE__)
170
+ // macOS implementation
171
+ #else
172
+ if (pImpl->nativeWindow) {
173
+ gtk_window_set_keep_above(GTK_WINDOW(pImpl->nativeWindow), enabled);
174
+ }
175
+ #endif
176
+ }
177
+
178
+ void WindowManager::setResizable(bool enabled) {
179
+ #ifdef _WIN32
180
+ if (pImpl->nativeWindow) {
181
+ LONG style = GetWindowLong(pImpl->hwnd(), GWL_STYLE);
182
+ if (enabled) {
183
+ style |= WS_THICKFRAME;
184
+ } else {
185
+ style &= ~WS_THICKFRAME;
186
+ }
187
+ SetWindowLong(pImpl->hwnd(), GWL_STYLE, style);
188
+ }
189
+ #elif defined(__APPLE__)
190
+ // macOS implementation
191
+ #else
192
+ if (pImpl->nativeWindow) {
193
+ gtk_window_set_resizable(GTK_WINDOW(pImpl->nativeWindow), enabled);
194
+ }
195
+ #endif
196
+ }
197
+
198
+ void WindowManager::setDecorations(bool enabled) {
199
+ #ifdef _WIN32
200
+ if (pImpl->nativeWindow) {
201
+ LONG style = GetWindowLong(pImpl->hwnd(), GWL_STYLE);
202
+ if (enabled) {
203
+ style |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
204
+ } else {
205
+ style &= ~(WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX);
206
+ }
207
+ SetWindowLong(pImpl->hwnd(), GWL_STYLE, style);
208
+ }
209
+ #elif defined(__APPLE__)
210
+ // macOS implementation
211
+ #else
212
+ if (pImpl->nativeWindow) {
213
+ gtk_window_set_decorated(GTK_WINDOW(pImpl->nativeWindow), enabled);
214
+ }
215
+ #endif
216
+ }
217
+
218
+ void WindowManager::setSkipTaskbar(bool enabled) {
219
+ #ifdef _WIN32
220
+ if (pImpl->nativeWindow) {
221
+ LONG exStyle = GetWindowLong(pImpl->hwnd(), GWL_EXSTYLE);
222
+ if (enabled) {
223
+ exStyle |= WS_EX_TOOLWINDOW;
224
+ } else {
225
+ exStyle &= ~WS_EX_TOOLWINDOW;
226
+ }
227
+ SetWindowLong(pImpl->hwnd(), GWL_EXSTYLE, exStyle);
228
+ }
229
+ #endif
230
+ }
231
+
232
+ void WindowManager::setTransparency(double alpha) {
233
+ #ifdef _WIN32
234
+ if (pImpl->nativeWindow) {
235
+ LONG exStyle = GetWindowLong(pImpl->hwnd(), GWL_EXSTYLE);
236
+ SetWindowLong(pImpl->hwnd(), GWL_EXSTYLE, exStyle | WS_EX_LAYERED);
237
+ SetLayeredWindowAttributes(pImpl->hwnd(), 0, (BYTE)(alpha * 255),
238
+ LWA_ALPHA);
239
+ }
240
+ #elif defined(__APPLE__)
241
+ // macOS implementation
242
+ #else
243
+ if (pImpl->nativeWindow) {
244
+ gtk_widget_set_opacity(GTK_WIDGET(pImpl->nativeWindow), alpha);
245
+ }
246
+ #endif
247
+ }
248
+
249
+ void WindowManager::minimize() {
250
+ #ifdef _WIN32
251
+ if (pImpl->nativeWindow) {
252
+ ShowWindow(pImpl->hwnd(), SW_MINIMIZE);
253
+ }
254
+ #elif defined(__APPLE__)
255
+ // macOS implementation
256
+ #else
257
+ if (pImpl->nativeWindow) {
258
+ gtk_window_iconify(GTK_WINDOW(pImpl->nativeWindow));
259
+ }
260
+ #endif
261
+ }
262
+
263
+ void WindowManager::maximize() {
264
+ #ifdef _WIN32
265
+ if (pImpl->nativeWindow) {
266
+ ShowWindow(pImpl->hwnd(), SW_MAXIMIZE);
267
+ }
268
+ #elif defined(__APPLE__)
269
+ // macOS implementation
270
+ #else
271
+ if (pImpl->nativeWindow) {
272
+ gtk_window_maximize(GTK_WINDOW(pImpl->nativeWindow));
273
+ }
274
+ #endif
275
+ }
276
+
277
+ void WindowManager::restore() {
278
+ #ifdef _WIN32
279
+ if (pImpl->nativeWindow) {
280
+ ShowWindow(pImpl->hwnd(), SW_RESTORE);
281
+ }
282
+ #elif defined(__APPLE__)
283
+ // macOS implementation
284
+ #else
285
+ if (pImpl->nativeWindow) {
286
+ gtk_window_unmaximize(GTK_WINDOW(pImpl->nativeWindow));
287
+ }
288
+ #endif
289
+ }
290
+
291
+ void WindowManager::show() {
292
+ pImpl->visible = true;
293
+ #ifdef _WIN32
294
+ if (pImpl->nativeWindow) {
295
+ ShowWindow(pImpl->hwnd(), SW_SHOW);
296
+ }
297
+ #elif defined(__APPLE__)
298
+ // macOS implementation
299
+ #else
300
+ if (pImpl->nativeWindow) {
301
+ gtk_widget_show(GTK_WIDGET(pImpl->nativeWindow));
302
+ }
303
+ #endif
304
+ }
305
+
306
+ void WindowManager::hide() {
307
+ pImpl->visible = false;
308
+ #ifdef _WIN32
309
+ if (pImpl->nativeWindow) {
310
+ ShowWindow(pImpl->hwnd(), SW_HIDE);
311
+ }
312
+ #elif defined(__APPLE__)
313
+ // macOS implementation
314
+ #else
315
+ if (pImpl->nativeWindow) {
316
+ gtk_widget_hide(GTK_WIDGET(pImpl->nativeWindow));
317
+ }
318
+ #endif
319
+ }
320
+
321
+ void WindowManager::close() {
322
+ #ifdef _WIN32
323
+ if (pImpl->nativeWindow) {
324
+ PostMessage(pImpl->hwnd(), WM_CLOSE, 0, 0);
325
+ }
326
+ #elif defined(__APPLE__)
327
+ // macOS implementation
328
+ #else
329
+ if (pImpl->nativeWindow) {
330
+ gtk_window_close(GTK_WINDOW(pImpl->nativeWindow));
331
+ }
332
+ #endif
333
+ }
334
+
335
+ bool WindowManager::isMaximized() const { return pImpl->maximized; }
336
+
337
+ bool WindowManager::isMinimized() const { return pImpl->minimized; }
338
+
339
+ bool WindowManager::isVisible() const { return pImpl->visible; }
340
+
341
+ } // namespace plusui
@@ -0,0 +1,73 @@
1
+ #ifndef PLUSUI_APP_H
2
+ #define PLUSUI_APP_H
3
+
4
+ #include "tray.hpp"
5
+ #include "webview.hpp"
6
+ #include "window_manager.hpp"
7
+ #include <functional>
8
+ #include <future>
9
+ #include <memory>
10
+ #include <string>
11
+
12
+ namespace plusui {
13
+
14
+ class App {
15
+ public:
16
+ App();
17
+ ~App();
18
+
19
+ class Builder;
20
+
21
+ void run();
22
+ void quit();
23
+
24
+ private:
25
+ struct Impl;
26
+ std::unique_ptr<Impl> pImpl;
27
+ };
28
+
29
+ class App::Builder {
30
+ public:
31
+ struct Config {
32
+ std::string title = "PlusUI App";
33
+ int width = 1200;
34
+ int height = 800;
35
+ bool resizable = true;
36
+ bool devtools = true;
37
+ std::string trayIconPath;
38
+ std::string trayTooltip;
39
+ bool alwaysOnTop = false;
40
+ bool centered = true;
41
+ bool transparent = false;
42
+ bool decorations = true;
43
+ bool skipTaskbar = false;
44
+ bool scrollbars = true;
45
+ };
46
+
47
+ Builder();
48
+
49
+ Builder &title(const std::string &t);
50
+ Builder &width(int w);
51
+ Builder &height(int h);
52
+ Builder &resizable(bool r);
53
+ Builder &devtools(bool d);
54
+ Builder &trayIcon(const std::string &icon);
55
+ Builder &trayTooltip(const std::string &tooltip);
56
+ Builder &alwaysOnTop(bool top);
57
+ Builder &centered(bool center);
58
+ Builder &transparent(bool transparent);
59
+ Builder &decorations(bool decorations);
60
+ Builder &skipTaskbar(bool skip);
61
+ Builder &scrollbars(bool show);
62
+
63
+ WebView build();
64
+
65
+ private:
66
+ Config config;
67
+ };
68
+
69
+ App::Builder createApp();
70
+
71
+ } // namespace plusui
72
+
73
+ #endif
@@ -0,0 +1,66 @@
1
+ #pragma once
2
+
3
+ #include <functional>
4
+ #include <memory>
5
+ #include <string>
6
+ #include <map>
7
+
8
+ namespace plusui {
9
+
10
+ class WebView;
11
+
12
+ struct BrowserState {
13
+ std::string url;
14
+ std::string title;
15
+ bool canGoBack = false;
16
+ bool canGoForward = false;
17
+ bool isLoading = false;
18
+ };
19
+
20
+ struct RouteConfig {
21
+ std::string path;
22
+ std::string url;
23
+ };
24
+
25
+ class Browser {
26
+ public:
27
+ using NavigateCallback = std::function<void(const std::string& url)>;
28
+ using StateCallback = std::function<void(const BrowserState& state)>;
29
+ using LoadCallback = std::function<void()>;
30
+
31
+ Browser();
32
+ ~Browser();
33
+
34
+ static Browser create(WebView* webview);
35
+
36
+ void navigate(const std::string& url);
37
+ void goBack();
38
+ void goForward();
39
+ void reload();
40
+ void stop();
41
+
42
+ std::string getURL() const;
43
+ std::string getTitle() const;
44
+ BrowserState getState() const;
45
+
46
+ bool canGoBack() const;
47
+ bool canGoForward() const;
48
+ bool isLoading() const;
49
+
50
+ void onNavigate(NavigateCallback callback);
51
+ void onStateChange(StateCallback callback);
52
+ void onLoadStart(LoadCallback callback);
53
+ void onLoadEnd(LoadCallback callback);
54
+ void onLoadError(std::function<void(const std::string& error)> callback);
55
+
56
+ void setRoutes(const std::map<std::string, std::string>& routes);
57
+ void push(const std::string& route);
58
+ void replace(const std::string& route);
59
+ std::string getCurrentRoute() const;
60
+
61
+ private:
62
+ struct Impl;
63
+ std::shared_ptr<Impl> pImpl;
64
+ };
65
+
66
+ } // namespace plusui
@@ -0,0 +1,41 @@
1
+ #pragma once
2
+
3
+ #include <string>
4
+ #include <vector>
5
+ #include <functional>
6
+
7
+ namespace PlusUI {
8
+
9
+ /**
10
+ * Clipboard - Cross-platform clipboard management
11
+ *
12
+ * Provides access to system clipboard for text and images.
13
+ * Supports clipboard change events.
14
+ */
15
+ class Clipboard {
16
+ public:
17
+ Clipboard();
18
+ ~Clipboard();
19
+
20
+ // Text operations
21
+ std::string getText();
22
+ void setText(const std::string& text);
23
+ bool hasText();
24
+
25
+ // Image operations (base64 encoded)
26
+ std::string getImage();
27
+ void setImage(const std::string& base64Data);
28
+ bool hasImage();
29
+
30
+ // Clear clipboard
31
+ void clear();
32
+
33
+ // Clipboard change events
34
+ void onClipboardChange(std::function<void(const std::string&)> callback);
35
+
36
+ private:
37
+ struct Impl;
38
+ Impl* pImpl;
39
+ };
40
+
41
+ } // namespace PlusUI
@@ -0,0 +1,58 @@
1
+ // Event API - Bidirectional custom events
2
+ #pragma once
3
+ #include <string>
4
+ #include <functional>
5
+ #include <cstdint>
6
+ #include <cstddef>
7
+
8
+ namespace plusui {
9
+ namespace event {
10
+
11
+ using ListenerId = std::uint64_t;
12
+ using EventData = std::string;
13
+ using EventCallback = std::function<void(const EventData&)>;
14
+ using AnyEventCallback = std::function<void(const std::string&, const EventData&)>;
15
+
16
+ /**
17
+ * Simple Bidirectional Event System
18
+ *
19
+ * Backend:
20
+ * event::on("myEvent", callback) // Listen for events from frontend
21
+ * event::emit("myEvent", data) // Send events to frontend
22
+ *
23
+ * Frontend:
24
+ * event.on("myEvent", callback) // Listen for events from backend
25
+ * event.emit("myEvent", data) // Send events to backend
26
+ *
27
+ * Users create custom events anywhere in their app - bindings auto-generated on build
28
+ */
29
+
30
+ // Listen for events emitted from frontend
31
+ ListenerId on(const std::string& name, EventCallback callback);
32
+
33
+ // Listen once, then auto-unsubscribe
34
+ ListenerId once(const std::string& name, EventCallback callback);
35
+
36
+ // Listen to every event emitted from frontend
37
+ ListenerId on_any(AnyEventCallback callback);
38
+
39
+ // Remove a specific listener from an event
40
+ bool off(const std::string& name, ListenerId id);
41
+
42
+ // Remove a specific global listener
43
+ bool off_any(ListenerId id);
44
+
45
+ // Remove all listeners for a given event name
46
+ std::size_t off_all(const std::string& name);
47
+
48
+ // Remove all listeners in the event system
49
+ void clear();
50
+
51
+ // Emit events to frontend
52
+ void emit(const std::string& name, const EventData& data);
53
+
54
+ // Internal: Dispatch from frontend (used by binding system)
55
+ void __dispatch_from_frontend__(const std::string& name, const EventData& data);
56
+
57
+ } // namespace event
58
+ } // namespace plusui