plusui-native-core 0.1.0

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 (70) hide show
  1. package/Core/CMakeLists.txt +34 -0
  2. package/Core/README.md +29 -0
  3. package/Core/build/win32/x64/ALL_BUILD.vcxproj +185 -0
  4. package/Core/build/win32/x64/ALL_BUILD.vcxproj.filters +8 -0
  5. package/Core/build/win32/x64/CMakeCache.txt +335 -0
  6. package/Core/build/win32/x64/CMakeFiles/11f7f2f432927ec8d1861dc42d4bd679/INSTALL_force.rule +1 -0
  7. package/Core/build/win32/x64/CMakeFiles/11f7f2f432927ec8d1861dc42d4bd679/generate.stamp.rule +1 -0
  8. package/Core/build/win32/x64/CMakeFiles/4.2.3/CMakeCXXCompiler.cmake +104 -0
  9. package/Core/build/win32/x64/CMakeFiles/4.2.3/CMakeDetermineCompilerABI_CXX.bin +0 -0
  10. package/Core/build/win32/x64/CMakeFiles/4.2.3/CMakeRCCompiler.cmake +6 -0
  11. package/Core/build/win32/x64/CMakeFiles/4.2.3/CMakeSystem.cmake +15 -0
  12. package/Core/build/win32/x64/CMakeFiles/4.2.3/CompilerIdCXX/CMakeCXXCompilerId.cpp +949 -0
  13. package/Core/build/win32/x64/CMakeFiles/4.2.3/CompilerIdCXX/CompilerIdCXX.exe +0 -0
  14. package/Core/build/win32/x64/CMakeFiles/4.2.3/CompilerIdCXX/CompilerIdCXX.vcxproj +72 -0
  15. package/Core/build/win32/x64/CMakeFiles/4.2.3/CompilerIdCXX/Debug/CMakeCXXCompilerId.obj +0 -0
  16. package/Core/build/win32/x64/CMakeFiles/4.2.3/CompilerIdCXX/Debug/CompilerIdCXX.exe.recipe +11 -0
  17. package/Core/build/win32/x64/CMakeFiles/4.2.3/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.command.1.tlog +2 -0
  18. package/Core/build/win32/x64/CMakeFiles/4.2.3/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.read.1.tlog +4 -0
  19. package/Core/build/win32/x64/CMakeFiles/4.2.3/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CL.write.1.tlog +2 -0
  20. package/Core/build/win32/x64/CMakeFiles/4.2.3/CompilerIdCXX/Debug/CompilerIdCXX.tlog/Cl.items.tlog +1 -0
  21. package/Core/build/win32/x64/CMakeFiles/4.2.3/CompilerIdCXX/Debug/CompilerIdCXX.tlog/CompilerIdCXX.lastbuildstate +2 -0
  22. package/Core/build/win32/x64/CMakeFiles/4.2.3/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.command.1.tlog +2 -0
  23. package/Core/build/win32/x64/CMakeFiles/4.2.3/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.read.1.tlog +22 -0
  24. package/Core/build/win32/x64/CMakeFiles/4.2.3/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.secondary.1.tlog +1 -0
  25. package/Core/build/win32/x64/CMakeFiles/4.2.3/CompilerIdCXX/Debug/CompilerIdCXX.tlog/link.write.1.tlog +2 -0
  26. package/Core/build/win32/x64/CMakeFiles/4.2.3/VCTargetsPath/x64/Debug/VCTargetsPath.recipe +11 -0
  27. package/Core/build/win32/x64/CMakeFiles/4.2.3/VCTargetsPath/x64/Debug/VCTargetsPath.tlog/VCTargetsPath.lastbuildstate +2 -0
  28. package/Core/build/win32/x64/CMakeFiles/4.2.3/VCTargetsPath.txt +1 -0
  29. package/Core/build/win32/x64/CMakeFiles/4.2.3/VCTargetsPath.vcxproj +31 -0
  30. package/Core/build/win32/x64/CMakeFiles/CMakeConfigureLog.yaml +2698 -0
  31. package/Core/build/win32/x64/CMakeFiles/InstallScripts.json +7 -0
  32. package/Core/build/win32/x64/CMakeFiles/TargetDirectories.txt +4 -0
  33. package/Core/build/win32/x64/CMakeFiles/cmake.check_cache +1 -0
  34. package/Core/build/win32/x64/CMakeFiles/generate.stamp +1 -0
  35. package/Core/build/win32/x64/CMakeFiles/generate.stamp.depend +34 -0
  36. package/Core/build/win32/x64/CMakeFiles/generate.stamp.list +1 -0
  37. package/Core/build/win32/x64/Capsule.sln +67 -0
  38. package/Core/build/win32/x64/INSTALL.vcxproj +209 -0
  39. package/Core/build/win32/x64/INSTALL.vcxproj.filters +13 -0
  40. package/Core/build/win32/x64/ZERO_CHECK.vcxproj +179 -0
  41. package/Core/build/win32/x64/ZERO_CHECK.vcxproj.filters +13 -0
  42. package/Core/build/win32/x64/capsule.dir/Release/capsule.tlog/CL.command.1.tlog +2 -0
  43. package/Core/build/win32/x64/capsule.dir/Release/capsule.tlog/CustomBuild.command.1.tlog +10 -0
  44. package/Core/build/win32/x64/capsule.dir/Release/capsule.tlog/CustomBuild.read.1.tlog +33 -0
  45. package/Core/build/win32/x64/capsule.dir/Release/capsule.tlog/CustomBuild.write.1.tlog +2 -0
  46. package/Core/build/win32/x64/capsule.dir/Release/capsule.tlog/capsule.lastbuildstate +2 -0
  47. package/Core/build/win32/x64/capsule.dir/Release/capsule.tlog/unsuccessfulbuild +0 -0
  48. package/Core/build/win32/x64/capsule.vcxproj +332 -0
  49. package/Core/build/win32/x64/capsule.vcxproj.filters +25 -0
  50. package/Core/build/win32/x64/cmake_install.cmake +72 -0
  51. package/Core/build/win32/x64/x64/Release/ZERO_CHECK/ZERO_CHECK.recipe +11 -0
  52. package/Core/build/win32/x64/x64/Release/ZERO_CHECK/ZERO_CHECK.tlog/CustomBuild.command.1.tlog +10 -0
  53. package/Core/build/win32/x64/x64/Release/ZERO_CHECK/ZERO_CHECK.tlog/CustomBuild.read.1.tlog +34 -0
  54. package/Core/build/win32/x64/x64/Release/ZERO_CHECK/ZERO_CHECK.tlog/CustomBuild.write.1.tlog +2 -0
  55. package/Core/build/win32/x64/x64/Release/ZERO_CHECK/ZERO_CHECK.tlog/ZERO_CHECK.lastbuildstate +2 -0
  56. package/Core/include/app.hpp +121 -0
  57. package/Core/include/display.hpp +90 -0
  58. package/Core/include/keyboard.hpp +135 -0
  59. package/Core/include/menu.hpp +79 -0
  60. package/Core/include/tray.hpp +81 -0
  61. package/Core/include/window.hpp +106 -0
  62. package/Core/src/app.cpp +311 -0
  63. package/Core/src/display.cpp +424 -0
  64. package/Core/src/tray.cpp +275 -0
  65. package/Core/src/window.cpp +528 -0
  66. package/Core/vendor/webview.h +551 -0
  67. package/dist/index.d.ts +205 -0
  68. package/dist/index.js +198 -0
  69. package/package.json +19 -0
  70. package/src/index.ts +574 -0
@@ -0,0 +1,528 @@
1
+ #include "window.hpp"
2
+ #include "display.hpp"
3
+ #include <iostream>
4
+ #include <map>
5
+
6
+ #ifdef _WIN32
7
+ #include <windows.h>
8
+ #elif defined(__APPLE__)
9
+ #include <Cocoa/Cocoa.h>
10
+ #include <objc/objc-runtime.h>
11
+ #else
12
+ #include <gtk/gtk.h>
13
+ #endif
14
+
15
+ namespace plusui {
16
+
17
+ struct Window::Impl {
18
+ void* nativeWindow = nullptr;
19
+ WindowConfig config;
20
+ WindowState state;
21
+
22
+ MoveCallback moveCallback;
23
+ ResizeCallback resizeCallback;
24
+ CloseCallback closeCallback;
25
+ FocusCallback focusCallback;
26
+ StateCallback stateCallback;
27
+
28
+ #ifdef _WIN32
29
+ HWND hwnd = nullptr;
30
+ WNDPROC originalProc = nullptr;
31
+
32
+ static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
33
+ Window* w = nullptr;
34
+ if (msg == WM_NCCREATE) {
35
+ auto cs = (LPCREATESTRUCT)lp;
36
+ w = (Window*)cs->lpCreateParams;
37
+ SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)w);
38
+ } else {
39
+ w = (Window*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
40
+ }
41
+
42
+ if (w && w->pImpl) {
43
+ switch (msg) {
44
+ case WM_MOVE:
45
+ if (w->pImpl->moveCallback) {
46
+ int x = (int)(short)LOWORD(lp);
47
+ int y = (int)(short)HIWORD(lp);
48
+ w->pImpl->moveCallback(x, y);
49
+ }
50
+ break;
51
+ case WM_SIZE:
52
+ if (w->pImpl->resizeCallback) {
53
+ int w = LOWORD(lp);
54
+ int h = HIWORD(lp);
55
+ w->pImpl->resizeCallback(w, h);
56
+ }
57
+ break;
58
+ case WM_CLOSE:
59
+ if (w->pImpl->closeCallback) {
60
+ w->pImpl->closeCallback();
61
+ }
62
+ break;
63
+ case WM_SETFOCUS:
64
+ if (w->pImpl->focusCallback) {
65
+ w->pImpl->focusCallback(true);
66
+ }
67
+ break;
68
+ case WM_KILLFOCUS:
69
+ if (w->pImpl->focusCallback) {
70
+ w->pImpl->focusCallback(false);
71
+ }
72
+ break;
73
+ }
74
+ }
75
+ return DefWindowProc(hwnd, msg, wp, lp);
76
+ }
77
+ #endif
78
+ };
79
+
80
+ Window::Window() : pImpl(std::make_unique<Impl>()) {}
81
+
82
+ Window::~Window() = default;
83
+
84
+ Window Window::create(const WindowConfig& config) {
85
+ Window w;
86
+ w.pImpl->config = config;
87
+
88
+ #ifdef _WIN32
89
+ WNDCLASSEX wc = {};
90
+ wc.cbSize = sizeof(WNDCLASSEX);
91
+ wc.lpfnWndProc = Impl::wndProc;
92
+ wc.hInstance = GetModuleHandle(nullptr);
93
+ wc.lpszClassName = L"PLUSUI_WINDOW";
94
+ wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
95
+ RegisterClassEx(&wc);
96
+
97
+ DWORD style = WS_OVERLAPPEDWINDOW;
98
+ if (!config.resizable) style &= ~WS_THICKFRAME;
99
+ if (!config.minimizable) style &= ~WS_MINIMIZEBOX;
100
+ if (!config.closable) style &= ~WS_SYSMENU;
101
+
102
+ std::wstring wtitle(config.title.begin(), config.title.end());
103
+ w.pImpl->hwnd = CreateWindowExW(
104
+ 0, L"PLUSUI_WINDOW",
105
+ wtitle.c_str(),
106
+ style,
107
+ config.x >= 0 ? config.x : CW_USEDEFAULT,
108
+ config.y >= 0 ? config.y : CW_USEDEFAULT,
109
+ config.width, config.height,
110
+ nullptr, nullptr,
111
+ GetModuleHandle(nullptr),
112
+ &w
113
+ );
114
+
115
+ w.pImpl->nativeWindow = (void*)w.pImpl->hwnd;
116
+ w.pImpl->state.width = config.width;
117
+ w.pImpl->state.height = config.height;
118
+
119
+ if (config.center) {
120
+ RECT screen;
121
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &screen, 0);
122
+ int x = (screen.right - config.width) / 2;
123
+ int y = (screen.bottom - config.height) / 2;
124
+ SetWindowPos(w.pImpl->hwnd, nullptr, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
125
+ }
126
+
127
+ if (config.alwaysOnTop) {
128
+ SetWindowPos(w.pImpl->hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
129
+ }
130
+
131
+ #elif defined(__APPLE__)
132
+ NSWindow* nswin = [[NSWindow alloc]
133
+ initWithContentRect:NSMakeRect(config.x >= 0 ? config.x : 100,
134
+ config.y >= 0 ? config.y : 100,
135
+ config.width, config.height)
136
+ styleMask:(config.resizable ? NSWindowStyleMaskResizable : 0) |
137
+ NSWindowStyleMaskTitled |
138
+ NSWindowStyleMaskClosable |
139
+ (config.minimizable ? NSWindowStyleMaskMiniaturizable : 0)
140
+ backing:NSBackingStoreBuffered
141
+ defer:NO];
142
+
143
+ [nswin setTitle:[NSString stringWithUTF8String:config.title.c_str()]];
144
+ [nswin setReleasedWhenClosed:NO];
145
+
146
+ if (config.center) {
147
+ [nswin center];
148
+ }
149
+
150
+ if (config.alwaysOnTop) {
151
+ [nswin setLevel:NSFloatingWindowLevel];
152
+ }
153
+
154
+ w.pImpl->nativeWindow = (__bridge void*)nswin;
155
+
156
+ #else
157
+ gtk_init_check(0, nullptr);
158
+
159
+ GtkWindow* gtkwin = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
160
+ gtk_window_set_title(gtkwin, config.title.c_str());
161
+ gtk_window_set_default_size(gtkwin, config.width, config.height);
162
+
163
+ if (config.x >= 0 && config.y >= 0) {
164
+ gtk_window_move(gtkwin, config.x, config.y);
165
+ } else if (config.center) {
166
+ gtk_window_set_position(gtkwin, GTK_WIN_POS_CENTER);
167
+ }
168
+
169
+ if (!config.resizable) {
170
+ gtk_window_set_resizable(gtkwin, FALSE);
171
+ }
172
+
173
+ if (config.alwaysOnTop) {
174
+ gtk_window_set_keep_above(gtkwin, TRUE);
175
+ }
176
+
177
+ w.pImpl->nativeWindow = (void*)gtkwin;
178
+ #endif
179
+
180
+ return w;
181
+ }
182
+
183
+ void Window::setTitle(const std::string& title) {
184
+ pImpl->config.title = title;
185
+ #ifdef _WIN32
186
+ if (pImpl->hwnd) SetWindowTextA(pImpl->hwnd, title.c_str());
187
+ #elif defined(__APPLE__)
188
+ if (pImpl->nativeWindow) {
189
+ NSWindow* nswin = (__bridge NSWindow*)pImpl->nativeWindow;
190
+ [nswin setTitle:[NSString stringWithUTF8String:title.c_str()]];
191
+ }
192
+ #else
193
+ if (pImpl->nativeWindow) {
194
+ gtk_window_set_title(GTK_WINDOW(pImpl->nativeWindow), title.c_str());
195
+ }
196
+ #endif
197
+ }
198
+
199
+ std::string Window::getTitle() const {
200
+ return pImpl->config.title;
201
+ }
202
+
203
+ void Window::setSize(int width, int height) {
204
+ pImpl->config.width = width;
205
+ pImpl->config.height = height;
206
+ #ifdef _WIN32
207
+ if (pImpl->hwnd) SetWindowPos(pImpl->hwnd, nullptr, 0, 0, width, height, SWP_NOZORDER | SWP_NOMOVE);
208
+ #elif defined(__APPLE__)
209
+ if (pImpl->nativeWindow) {
210
+ NSWindow* nswin = (__bridge NSWindow*)pImpl->nativeWindow;
211
+ [nswin setContentSize:NSMakeSize(width, height)];
212
+ }
213
+ #else
214
+ if (pImpl->nativeWindow) {
215
+ gtk_window_resize(GTK_WINDOW(pImpl->nativeWindow), width, height);
216
+ }
217
+ #endif
218
+ }
219
+
220
+ void Window::getSize(int& width, int& height) const {
221
+ width = pImpl->state.width;
222
+ height = pImpl->state.height;
223
+ }
224
+
225
+ void Window::setMinSize(int minWidth, int minHeight) {
226
+ pImpl->config.minWidth = minWidth;
227
+ pImpl->config.minHeight = minHeight;
228
+ #ifdef _WIN32
229
+ if (pImpl->hwnd) {
230
+ SetWindowLongPtr(pImpl->hwnd, GWL_STYLE,
231
+ GetWindowLong(pImpl->hwnd, GWL_STYLE) | WS_THICKFRAME);
232
+ }
233
+ #endif
234
+ }
235
+
236
+ void Window::setMaxSize(int maxWidth, int maxHeight) {
237
+ pImpl->config.maxWidth = maxWidth;
238
+ pImpl->config.maxHeight = maxHeight;
239
+ }
240
+
241
+ void Window::setPosition(int x, int y) {
242
+ pImpl->config.x = x;
243
+ pImpl->config.y = y;
244
+ #ifdef _WIN32
245
+ if (pImpl->hwnd) SetWindowPos(pImpl->hwnd, nullptr, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
246
+ #elif defined(__APPLE__)
247
+ if (pImpl->nativeWindow) {
248
+ NSWindow* nswin = (__bridge NSWindow*)pImpl->nativeWindow;
249
+ [nswin setFrameOrigin:NSMakePoint(x, y)];
250
+ }
251
+ #else
252
+ if (pImpl->nativeWindow) {
253
+ gtk_window_move(GTK_WINDOW(pImpl->nativeWindow), x, y);
254
+ }
255
+ #endif
256
+ }
257
+
258
+ void Window::getPosition(int& x, int& y) const {
259
+ x = pImpl->state.x;
260
+ y = pImpl->state.y;
261
+ }
262
+
263
+ void Window::center() {
264
+ #ifdef _WIN32
265
+ if (pImpl->hwnd) {
266
+ RECT rc, screen;
267
+ GetWindowRect(pImpl->hwnd, &rc);
268
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &screen, 0);
269
+ int x = (screen.right - (rc.right - rc.left)) / 2;
270
+ int y = (screen.bottom - (rc.bottom - rc.top)) / 2;
271
+ SetWindowPos(pImpl->hwnd, nullptr, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
272
+ }
273
+ #elif defined(__APPLE__)
274
+ if (pImpl->nativeWindow) {
275
+ NSWindow* nswin = (__bridge NSWindow*)pImpl->nativeWindow;
276
+ [nswin center];
277
+ }
278
+ #else
279
+ if (pImpl->nativeWindow) {
280
+ gtk_window_set_position(GTK_WINDOW(pImpl->nativeWindow), GTK_WIN_POS_CENTER);
281
+ }
282
+ #endif
283
+ }
284
+
285
+ void Window::setFullscreen(bool enabled) {
286
+ pImpl->config.fullscreen = enabled;
287
+ pImpl->state.isFullscreen = enabled;
288
+
289
+ #ifdef _WIN32
290
+ if (pImpl->hwnd) {
291
+ if (enabled) {
292
+ SetWindowLongPtr(pImpl->hwnd, GWL_STYLE,
293
+ GetWindowLong(pImpl->hwnd, GWL_STYLE) & ~WS_OVERLAPPEDWINDOW);
294
+ SetWindowPos(pImpl->hwnd, HWND_TOP, 0, 0,
295
+ GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN),
296
+ SWP_SHOWWINDOW);
297
+ } else {
298
+ SetWindowLongPtr(pImpl->hwnd, GWL_STYLE,
299
+ GetWindowLong(pImpl->hwnd, GWL_STYLE) | WS_OVERLAPPEDWINDOW);
300
+ SetWindowPos(pImpl->hwnd, nullptr, 0, 0, 0, 0,
301
+ SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
302
+ }
303
+ }
304
+ #elif defined(__APPLE__)
305
+ if (pImpl->nativeWindow) {
306
+ NSWindow* nswin = (__bridge NSWindow*)pImpl->nativeWindow;
307
+ if (enabled) {
308
+ [nswin toggleFullScreen:nil];
309
+ }
310
+ }
311
+ #else
312
+ if (pImpl->nativeWindow) {
313
+ if (enabled) {
314
+ gtk_window_fullscreen(GTK_WINDOW(pImpl->nativeWindow));
315
+ } else {
316
+ gtk_window_unfullscreen(GTK_WINDOW(pImpl->nativeWindow));
317
+ }
318
+ }
319
+ #endif
320
+ }
321
+
322
+ bool Window::isFullscreen() const {
323
+ return pImpl->state.isFullscreen;
324
+ }
325
+
326
+ void Window::minimize() {
327
+ #ifdef _WIN32
328
+ if (pImpl->hwnd) ShowWindow(pImpl->hwnd, SW_MINIMIZE);
329
+ #elif defined(__APPLE__)
330
+ if (pImpl->nativeWindow) {
331
+ NSWindow* nswin = (__bridge NSWindow*)pImpl->nativeWindow;
332
+ [nswin miniaturize:nil];
333
+ }
334
+ #else
335
+ if (pImpl->nativeWindow) {
336
+ gtk_window_iconify(GTK_WINDOW(pImpl->nativeWindow));
337
+ }
338
+ #endif
339
+ }
340
+
341
+ void Window::maximize() {
342
+ #ifdef _WIN32
343
+ if (pImpl->hwnd) ShowWindow(pImpl->hwnd, SW_MAXIMIZE);
344
+ #elif defined(__APPLE__)
345
+ if (pImpl->nativeWindow) {
346
+ NSWindow* nswin = (__bridge NSWindow*)pImpl->nativeWindow;
347
+ [nswin zoom:nil];
348
+ }
349
+ #else
350
+ if (pImpl->nativeWindow) {
351
+ gtk_window_maximize(GTK_WINDOW(pImpl->nativeWindow));
352
+ }
353
+ #endif
354
+ }
355
+
356
+ void Window::restore() {
357
+ #ifdef _WIN32
358
+ if (pImpl->hwnd) ShowWindow(pImpl->hwnd, SW_RESTORE);
359
+ #elif defined(__APPLE__)
360
+ if (pImpl->nativeWindow) {
361
+ NSWindow* nswin = (__bridge NSWindow*)pImpl->nativeWindow;
362
+ [nswin deminiaturize:nil];
363
+ }
364
+ #else
365
+ if (pImpl->nativeWindow) {
366
+ gtk_window_unmaximize(GTK_WINDOW(pImpl->nativeWindow));
367
+ gtk_window_deiconify(GTK_WINDOW(pImpl->nativeWindow));
368
+ }
369
+ #endif
370
+ }
371
+
372
+ bool Window::isMaximized() const {
373
+ return pImpl->state.isMaximized;
374
+ }
375
+
376
+ bool Window::isMinimized() const {
377
+ return pImpl->state.isMinimized;
378
+ }
379
+
380
+ void Window::show() {
381
+ pImpl->state.isVisible = true;
382
+ #ifdef _WIN32
383
+ if (pImpl->hwnd) ShowWindow(pImpl->hwnd, SW_SHOW);
384
+ #elif defined(__APPLE__)
385
+ if (pImpl->nativeWindow) {
386
+ NSWindow* nswin = (__bridge NSWindow*)pImpl->nativeWindow;
387
+ [nswin orderFront:nil];
388
+ }
389
+ #else
390
+ if (pImpl->nativeWindow) {
391
+ gtk_widget_show(GTK_WIDGET(pImpl->nativeWindow));
392
+ }
393
+ #endif
394
+ }
395
+
396
+ void Window::hide() {
397
+ pImpl->state.isVisible = false;
398
+ #ifdef _WIN32
399
+ if (pImpl->hwnd) ShowWindow(pImpl->hwnd, SW_HIDE);
400
+ #elif defined(__APPLE__)
401
+ if (pImpl->nativeWindow) {
402
+ NSWindow* nswin = (__bridge NSWindow*)pImpl->nativeWindow;
403
+ [nswin orderOut:nil];
404
+ }
405
+ #else
406
+ if (pImpl->nativeWindow) {
407
+ gtk_widget_hide(GTK_WIDGET(pImpl->nativeWindow));
408
+ }
409
+ #endif
410
+ }
411
+
412
+ bool Window::isVisible() const {
413
+ return pImpl->state.isVisible;
414
+ }
415
+
416
+ void Window::focus() {
417
+ #ifdef _WIN32
418
+ if (pImpl->hwnd) SetFocus(pImpl->hwnd);
419
+ #elif defined(__APPLE__)
420
+ if (pImpl->nativeWindow) {
421
+ NSWindow* nswin = (__bridge NSWindow*)pImpl->nativeWindow;
422
+ [nswin makeKeyAndOrderFront:nil];
423
+ }
424
+ #else
425
+ if (pImpl->nativeWindow) {
426
+ gtk_window_present(GTK_WINDOW(pImpl->nativeWindow));
427
+ }
428
+ #endif
429
+ }
430
+
431
+ bool Window::isFocused() const {
432
+ return pImpl->state.isFocused;
433
+ }
434
+
435
+ void Window::setAlwaysOnTop(bool enabled) {
436
+ pImpl->config.alwaysOnTop = enabled;
437
+ #ifdef _WIN32
438
+ if (pImpl->hwnd) {
439
+ SetWindowPos(pImpl->hwnd, enabled ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
440
+ }
441
+ #elif defined(__APPLE__)
442
+ if (pImpl->nativeWindow) {
443
+ NSWindow* nswin = (__bridge NSWindow*)pImpl->nativeWindow;
444
+ [nswin setLevel:enabled ? NSFloatingWindowLevel : NSNormalWindowLevel];
445
+ }
446
+ #else
447
+ if (pImpl->nativeWindow) {
448
+ gtk_window_set_keep_above(GTK_WINDOW(pImpl->nativeWindow), enabled);
449
+ }
450
+ #endif
451
+ }
452
+
453
+ void Window::setResizable(bool enabled) {
454
+ pImpl->config.resizable = enabled;
455
+ #ifdef _WIN32
456
+ if (pImpl->hwnd) {
457
+ SetWindowLongPtr(pImpl->hwnd, GWL_STYLE,
458
+ enabled ? GetWindowLong(pImpl->hwnd, GWL_STYLE) | WS_THICKFRAME
459
+ : GetWindowLong(pImpl->hwnd, GWL_STYLE) & ~WS_THICKFRAME);
460
+ }
461
+ #elif defined(__APPLE__)
462
+ // Handled in create
463
+ #else
464
+ if (pImpl->nativeWindow) {
465
+ gtk_window_set_resizable(GTK_WINDOW(pImpl->nativeWindow), enabled);
466
+ }
467
+ #endif
468
+ }
469
+
470
+ void Window::setDecorations(bool enabled) {
471
+ #ifdef _WIN32
472
+ if (pImpl->hwnd) {
473
+ SetWindowLongPtr(pImpl->hwnd, GWL_STYLE,
474
+ enabled ? GetWindowLong(pImpl->hwnd, GWL_STYLE) | WS_CAPTION
475
+ : GetWindowLong(pImpl->hwnd, GWL_STYLE) & ~WS_CAPTION);
476
+ }
477
+ #elif defined(__APPLE__)
478
+ if (pImpl->nativeWindow) {
479
+ NSWindow* nswin = (__bridge NSWindow*)pImpl->nativeWindow;
480
+ [nswin setStyleMask:enabled ? [nswin styleMask] | NSWindowStyleMaskTitled
481
+ : [nswin styleMask] & ~NSWindowStyleMaskTitled];
482
+ }
483
+ #else
484
+ if (pImpl->nativeWindow) {
485
+ // GTK handles this differently
486
+ }
487
+ #endif
488
+ }
489
+
490
+ void Window::setSkipTaskbar(bool enabled) {
491
+ #ifdef _WIN32
492
+ if (pImpl->hwnd) {
493
+ SetWindowLongPtr(pImpl->hwnd, GWL_EXSTYLE,
494
+ enabled ? GetWindowLong(pImpl->hwnd, GWL_EXSTYLE) | WS_EX_TOOLWINDOW
495
+ : GetWindowLong(pImpl->hwnd, GWL_EXSTYLE) & ~WS_EX_TOOLWINDOW);
496
+ }
497
+ #endif
498
+ }
499
+
500
+ WindowState Window::getState() const {
501
+ return pImpl->state;
502
+ }
503
+
504
+ void Window::onMove(MoveCallback callback) {
505
+ pImpl->moveCallback = callback;
506
+ }
507
+
508
+ void Window::onResize(ResizeCallback callback) {
509
+ pImpl->resizeCallback = callback;
510
+ }
511
+
512
+ void Window::onClose(CloseCallback callback) {
513
+ pImpl->closeCallback = callback;
514
+ }
515
+
516
+ void Window::onFocus(FocusCallback callback) {
517
+ pImpl->focusCallback = callback;
518
+ }
519
+
520
+ void Window::onStateChange(StateCallback callback) {
521
+ pImpl->stateCallback = callback;
522
+ }
523
+
524
+ void* Window::nativeHandle() const {
525
+ return pImpl->nativeWindow;
526
+ }
527
+
528
+ }