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.
- 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,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 ¢ered(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
|