windowpp 0.1.1

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 (88) hide show
  1. package/bin/windowpp.js +86 -0
  2. package/cmake/embed_assets.py +144 -0
  3. package/framework/CMakeLists.txt +176 -0
  4. package/framework/include/windowpp/windowpp.h +704 -0
  5. package/framework/src/AppData/API/AppData.ts +137 -0
  6. package/framework/src/AppData/appdata_bridge.h +138 -0
  7. package/framework/src/AppData/appdata_manager.cpp +126 -0
  8. package/framework/src/AppData/appdata_manager.h +3 -0
  9. package/framework/src/FileSystem/API/FileSystem.ts +389 -0
  10. package/framework/src/FileSystem/Linux/filesearch.cpp +148 -0
  11. package/framework/src/FileSystem/Linux/readfile.cpp +79 -0
  12. package/framework/src/FileSystem/Linux/savefile.cpp +333 -0
  13. package/framework/src/FileSystem/MacOS/filesearch.cpp +149 -0
  14. package/framework/src/FileSystem/MacOS/readfile.cpp +80 -0
  15. package/framework/src/FileSystem/MacOS/savefile.cpp +264 -0
  16. package/framework/src/FileSystem/Windows/filesearch.cpp +195 -0
  17. package/framework/src/FileSystem/Windows/readfile.cpp +122 -0
  18. package/framework/src/FileSystem/Windows/savefile.cpp +290 -0
  19. package/framework/src/FileSystem/file_index_service.cpp +262 -0
  20. package/framework/src/FileSystem/file_index_service.h +55 -0
  21. package/framework/src/FileSystem/filesystem_bridge.h +243 -0
  22. package/framework/src/FileSystem/filesystem_handler.h +93 -0
  23. package/framework/src/FileSystem/filesystem_json.h +241 -0
  24. package/framework/src/FileSystem/filesystem_search_service.cpp +414 -0
  25. package/framework/src/FileSystem/filesystem_search_service.h +94 -0
  26. package/framework/src/Input/API/Input.ts +161 -0
  27. package/framework/src/Input/Linux/linux_key_utils.h +135 -0
  28. package/framework/src/Input/MacOS/macos_key_utils.h +137 -0
  29. package/framework/src/Input/Windows/win32_key_utils.h +199 -0
  30. package/framework/src/Input/input_bridge.h +192 -0
  31. package/framework/src/Input/input_service.cpp +584 -0
  32. package/framework/src/Input/input_service.h +21 -0
  33. package/framework/src/application.cpp +29 -0
  34. package/framework/src/common/hit_test.cpp +40 -0
  35. package/framework/src/common/image_loader.cpp +24 -0
  36. package/framework/src/common/paths.cpp +75 -0
  37. package/framework/src/filedrop/filedrop.cpp +316 -0
  38. package/framework/src/filedrop/filedrop.css +421 -0
  39. package/framework/src/filedrop/filedrop.hpp +92 -0
  40. package/framework/src/filedrop/filedrop.ts +183 -0
  41. package/framework/src/platform/API/App.ts +156 -0
  42. package/framework/src/platform/API/Window.ts +249 -0
  43. package/framework/src/platform/linux/app_linux.cpp +256 -0
  44. package/framework/src/platform/linux/app_linux.h +64 -0
  45. package/framework/src/platform/linux/linux_helpers.cpp +26 -0
  46. package/framework/src/platform/linux/linux_helpers.h +19 -0
  47. package/framework/src/platform/linux/tray_linux.cpp +21 -0
  48. package/framework/src/platform/linux/tray_linux.h +26 -0
  49. package/framework/src/platform/linux/window_linux.cpp +256 -0
  50. package/framework/src/platform/linux/window_linux.h +70 -0
  51. package/framework/src/platform/macos/app_macos.h +59 -0
  52. package/framework/src/platform/macos/app_macos.mm +223 -0
  53. package/framework/src/platform/macos/macos_helpers.h +21 -0
  54. package/framework/src/platform/macos/tray_macos.h +22 -0
  55. package/framework/src/platform/macos/tray_macos.mm +53 -0
  56. package/framework/src/platform/macos/window_macos.h +74 -0
  57. package/framework/src/platform/macos/window_macos.mm +318 -0
  58. package/framework/src/platform/platform_bridge.h +514 -0
  59. package/framework/src/platform/platform_factory.cpp +33 -0
  60. package/framework/src/platform/platform_factory.h +19 -0
  61. package/framework/src/platform/win32/app_win32.cpp +572 -0
  62. package/framework/src/platform/win32/app_win32.h +83 -0
  63. package/framework/src/platform/win32/tray_win32.cpp +57 -0
  64. package/framework/src/platform/win32/tray_win32.h +30 -0
  65. package/framework/src/platform/win32/win32_helpers.h +61 -0
  66. package/framework/src/platform/win32/window_win32.cpp +267 -0
  67. package/framework/src/platform/win32/window_win32.h +79 -0
  68. package/framework/src/renderer/webgpu.h +128 -0
  69. package/framework/src/renderer/webview/include/WebView2.h +48014 -0
  70. package/framework/src/renderer/webview/include/WebView2EnvironmentOptions.h +342 -0
  71. package/framework/src/renderer/webview/webview.h +13 -0
  72. package/framework/src/renderer/webview/webview_linux.cpp +392 -0
  73. package/framework/src/renderer/webview/webview_macos.mm +388 -0
  74. package/framework/src/renderer/webview/webview_win32.cpp +688 -0
  75. package/framework/src/renderer/webview/x64/WebView2Loader.dll +0 -0
  76. package/framework/src/renderer/webview/x64/WebView2Loader.lib +0 -0
  77. package/framework/src/renderer/webview/x64/WebView2LoaderStatic.lib +0 -0
  78. package/lib/build.js +112 -0
  79. package/lib/create.js +283 -0
  80. package/lib/dev.js +155 -0
  81. package/package.json +24 -0
  82. package/scripts/publish.js +67 -0
  83. package/scripts/sync-framework.js +73 -0
  84. package/templates/solid/CMakeLists.txt +56 -0
  85. package/templates/solid/frontend/package.json +22 -0
  86. package/templates/solid/frontend/vite.config.ts +25 -0
  87. package/templates/solid/main.cpp +72 -0
  88. package/templates/solid/package.json +12 -0
@@ -0,0 +1,30 @@
1
+ // ============================================================================
2
+ // tray_win32.h — Win32 System Tray implementation
3
+ // ============================================================================
4
+
5
+ #pragma once
6
+
7
+ #define WIN32_LEAN_AND_MEAN
8
+ #define NOMINMAX
9
+ #include <windows.h>
10
+ #include <shellapi.h>
11
+ #include <windowpp/windowpp.h>
12
+
13
+ namespace wpp {
14
+
15
+ class Win32Tray {
16
+ public:
17
+ Win32Tray(const TrayConfig& config, HWND app_hwnd);
18
+ ~Win32Tray();
19
+
20
+ private:
21
+ TrayConfig config_;
22
+ HWND app_hwnd_;
23
+ NOTIFYICONDATAW nid_;
24
+ HMENU menu_;
25
+
26
+ void update_menu();
27
+ static LRESULT CALLBACK wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
28
+ };
29
+
30
+ } // namespace wpp
@@ -0,0 +1,61 @@
1
+ // ============================================================================
2
+ // win32_helpers.h — Win32 helper utilities
3
+ // ============================================================================
4
+
5
+ #pragma once
6
+
7
+ #define WIN32_LEAN_AND_MEAN
8
+ #define NOMINMAX
9
+ #include <windows.h>
10
+ #include <dwmapi.h>
11
+ #include <string>
12
+
13
+ namespace wpp {
14
+ namespace win32 {
15
+
16
+ inline std::wstring to_wide(const std::string& str) {
17
+ if (str.empty()) return {};
18
+ int size = MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), nullptr, 0);
19
+ std::wstring result(size, 0);
20
+ MultiByteToWideChar(CP_UTF8, 0, str.data(), (int)str.size(), result.data(), size);
21
+ return result;
22
+ }
23
+
24
+ inline std::string from_wide(const std::wstring& wstr) {
25
+ if (wstr.empty()) return {};
26
+ int size = WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(), nullptr, 0, nullptr, nullptr);
27
+ std::string result(size, 0);
28
+ WideCharToMultiByte(CP_UTF8, 0, wstr.data(), (int)wstr.size(), result.data(), size, nullptr, nullptr);
29
+ return result;
30
+ }
31
+
32
+ struct WindowClass {
33
+ WNDCLASSEXW wc = {};
34
+ ATOM atom = 0;
35
+
36
+ WindowClass(const std::string& name, WNDPROC proc) {
37
+ wc.cbSize = sizeof(WNDCLASSEXW);
38
+ wc.style = CS_HREDRAW | CS_VREDRAW;
39
+ wc.lpfnWndProc = proc;
40
+ wc.hInstance = GetModuleHandleW(nullptr);
41
+ wc.hCursor = LoadCursorW(nullptr, IDC_ARROW);
42
+ std::wstring wname = to_wide(name);
43
+ wc.lpszClassName = wname.c_str();
44
+ atom = RegisterClassExW(&wc);
45
+ }
46
+
47
+ ~WindowClass() {
48
+ if (atom) UnregisterClassW(MAKEINTATOM(atom), GetModuleHandleW(nullptr));
49
+ }
50
+ };
51
+
52
+ inline void set_window_long_ptr(HWND hwnd, int index, LONG_PTR value) {
53
+ SetWindowLongPtrW(hwnd, index, value);
54
+ }
55
+
56
+ inline LONG_PTR get_window_long_ptr(HWND hwnd, int index) {
57
+ return GetWindowLongPtrW(hwnd, index);
58
+ }
59
+
60
+ } // namespace win32
61
+ } // namespace wpp
@@ -0,0 +1,267 @@
1
+ // ============================================================================
2
+ // window_win32.cpp — Win32 Window implementation
3
+ // ============================================================================
4
+
5
+ #define WIN32_LEAN_AND_MEAN
6
+ #define NOMINMAX
7
+ #include "window_win32.h"
8
+ #include "win32_helpers.h"
9
+ #include <algorithm>
10
+
11
+ namespace wpp {
12
+
13
+ namespace {
14
+
15
+ constexpr wchar_t kWindowPPProp[] = L"WPP_WIN32_WINDOW_PTR";
16
+
17
+ }
18
+
19
+ Win32Window::Win32Window(const WindowConfig& config, HWND hwnd)
20
+ : config_(config), hwnd_(hwnd) {
21
+ if (hwnd_) {
22
+ SetPropW(hwnd_, kWindowPPProp, this);
23
+ }
24
+ }
25
+
26
+ Win32Window::~Win32Window() {
27
+ if (hwnd_ && IsWindow(hwnd_)) {
28
+ RemovePropW(hwnd_, kWindowPPProp);
29
+ }
30
+ if (hwnd_ && IsWindow(hwnd_)) {
31
+ DestroyWindow(hwnd_);
32
+ }
33
+ }
34
+
35
+ std::string Win32Window::title() const {
36
+ wchar_t buf[512];
37
+ GetWindowTextW(hwnd_, buf, 512);
38
+ return win32::from_wide(buf);
39
+ }
40
+
41
+ Size Win32Window::size() const {
42
+ RECT r;
43
+ GetWindowRect(hwnd_, &r);
44
+ return { (int)(r.right - r.left), (int)(r.bottom - r.top) };
45
+ }
46
+
47
+ Point Win32Window::position() const {
48
+ RECT r;
49
+ GetWindowRect(hwnd_, &r);
50
+ return { (int)r.left, (int)r.top };
51
+ }
52
+
53
+ WindowState Win32Window::state() const {
54
+ if (!IsWindowVisible(hwnd_)) return WindowState::Hidden;
55
+ WINDOWPLACEMENT wpp = {};
56
+ wpp.length = sizeof(wpp);
57
+ GetWindowPlacement(hwnd_, &wpp);
58
+ switch (wpp.showCmd) {
59
+ case SW_SHOWMAXIMIZED: return WindowState::Maximized;
60
+ case SW_SHOWMINIMIZED: return WindowState::Minimized;
61
+ default: return WindowState::Normal;
62
+ }
63
+ }
64
+
65
+ bool Win32Window::is_visible() const {
66
+ return IsWindowVisible(hwnd_) != 0;
67
+ }
68
+
69
+ bool Win32Window::is_focused() const {
70
+ return GetForegroundWindow() == hwnd_;
71
+ }
72
+
73
+ float Win32Window::scale_factor() const {
74
+ UINT dpi = GetDpiForWindow(hwnd_);
75
+ return dpi / 96.0f;
76
+ }
77
+
78
+ void Win32Window::set_title(const std::string& title) {
79
+ SetWindowTextW(hwnd_, win32::to_wide(title).c_str());
80
+ }
81
+
82
+ void Win32Window::set_size(int w, int h) {
83
+ SetWindowPos(hwnd_, nullptr, 0, 0, w, h, SWPP_NOZORDER | SWPP_NOMOVE);
84
+ }
85
+
86
+ void Win32Window::set_position(int x, int y) {
87
+ SetWindowPos(hwnd_, nullptr, x, y, 0, 0, SWPP_NOZORDER | SWPP_NOSIZE);
88
+ }
89
+
90
+ void Win32Window::set_min_size(int w, int h) {
91
+ config_.min_width = w;
92
+ config_.min_height = h;
93
+ }
94
+
95
+ void Win32Window::set_max_size(int w, int h) {
96
+ config_.max_width = w;
97
+ config_.max_height = h;
98
+ }
99
+
100
+ void Win32Window::set_resizable(bool v) {
101
+ config_.resizable = v;
102
+ if (v) {
103
+ SetWindowLongPtr(hwnd_, GWL_STYLE,
104
+ GetWindowLongPtr(hwnd_, GWL_STYLE) | WS_THICKFRAME);
105
+ } else {
106
+ SetWindowLongPtr(hwnd_, GWL_STYLE,
107
+ GetWindowLongPtr(hwnd_, GWL_STYLE) & ~WS_THICKFRAME);
108
+ }
109
+ }
110
+
111
+ void Win32Window::set_always_on_top(bool v) {
112
+ SetWindowPos(hwnd_, v ? HWND_TOPMOST : HWND_NOTOPMOST,
113
+ 0, 0, 0, 0, SWPP_NOMOVE | SWPP_NOSIZE);
114
+ }
115
+
116
+ void Win32Window::set_opacity(float v) {
117
+ SetLayeredWindowAttributes(hwnd_, 0, (BYTE)(v * 255), LWA_ALPHA);
118
+ }
119
+
120
+ void Win32Window::set_background(Color c) {
121
+ config_.background = c;
122
+ }
123
+
124
+ void Win32Window::set_cursor(CursorType c) {
125
+ LPCWSTR id;
126
+ switch (c) {
127
+ case CursorType::Arrow: id = IDC_ARROW; break;
128
+ case CursorType::Hand: id = IDC_HAND; break;
129
+ case CursorType::IBeam: id = IDC_IBEAM; break;
130
+ case CursorType::Crosshair: id = IDC_CROSS; break;
131
+ case CursorType::ResizeNS: id = IDC_SIZENS; break;
132
+ case CursorType::ResizeEW: id = IDC_SIZEWE; break;
133
+ case CursorType::ResizeNWSE: id = IDC_SIZENWSE; break;
134
+ case CursorType::ResizeNESW: id = IDC_SIZENESW; break;
135
+ case CursorType::Move: id = IDC_SIZEALL; break;
136
+ case CursorType::NotAllowed: id = IDC_NO; break;
137
+ case CursorType::Wait: id = IDC_WAIT; break;
138
+ default: id = IDC_ARROW; break;
139
+ }
140
+ SetCursor(LoadCursorW(nullptr, id));
141
+ }
142
+
143
+ void Win32Window::show() {
144
+ ShowWindow(hwnd_, SW_SHOW);
145
+ if (config_.on_shown) config_.on_shown();
146
+ }
147
+
148
+ void Win32Window::hide() {
149
+ ShowWindow(hwnd_, SW_HIDE);
150
+ if (config_.on_hidden) config_.on_hidden();
151
+ }
152
+
153
+ void Win32Window::close() {
154
+ if (hwnd_) SendMessage(hwnd_, WM_CLOSE, 0, 0);
155
+ }
156
+
157
+ void Win32Window::focus() {
158
+ SetForegroundWindow(hwnd_);
159
+ SetFocus(hwnd_);
160
+ }
161
+
162
+ void Win32Window::minimize() {
163
+ ShowWindow(hwnd_, SW_MINIMIZE);
164
+ }
165
+
166
+ void Win32Window::maximize() {
167
+ ShowWindow(hwnd_, SW_MAXIMIZE);
168
+ }
169
+
170
+ void Win32Window::restore() {
171
+ ShowWindow(hwnd_, SW_RESTORE);
172
+ }
173
+
174
+ void Win32Window::fullscreen() {
175
+ WindowState s = state();
176
+ if (s == WindowState::Fullscreen) {
177
+ restore();
178
+ } else {
179
+ RECT r;
180
+ MONITORINFO mi = { sizeof(mi) };
181
+ GetMonitorInfoW(MonitorFromWindow(hwnd_, MONITOR_DEFAULTTONEAREST), &mi);
182
+ r = mi.rcMonitor;
183
+ SetWindowPos(hwnd_, HWND_TOP, r.left, r.top,
184
+ r.right - r.left, r.bottom - r.top, SWPP_NOZORDER);
185
+ }
186
+ }
187
+
188
+ void Win32Window::center() {
189
+ RECT r;
190
+ GetWindowRect(hwnd_, &r);
191
+ int w = r.right - r.left;
192
+ int h = r.bottom - r.top;
193
+ MONITORINFO mi = { sizeof(mi) };
194
+ GetMonitorInfoW(MonitorFromWindow(hwnd_, MONITOR_DEFAULTTONEAREST), &mi);
195
+ int x = mi.rcWork.left + (mi.rcWork.right - mi.rcWork.left - w) / 2;
196
+ int y = mi.rcWork.top + (mi.rcWork.bottom - mi.rcWork.top - h) / 2;
197
+ SetWindowPos(hwnd_, nullptr, x, y, 0, 0, SWPP_NOZORDER | SWPP_NOSIZE);
198
+ }
199
+
200
+ void Win32Window::request_repaint() {
201
+ InvalidateRect(hwnd_, nullptr, TRUE);
202
+ }
203
+
204
+ void Win32Window::start_drag() {
205
+ ReleaseCapture();
206
+ SendMessage(hwnd_, WM_NCLBUTTONDOWN, HTCAPTION, 0);
207
+ }
208
+
209
+ void Win32Window::start_resize(HitTestRegion edge) {
210
+ ReleaseCapture();
211
+ WPARAM cmd = 0;
212
+ switch (edge) {
213
+ case HitTestRegion::ResizeTop: cmd = HTTOP; break;
214
+ case HitTestRegion::ResizeBottom: cmd = HTBOTTOM; break;
215
+ case HitTestRegion::ResizeLeft: cmd = HTLEFT; break;
216
+ case HitTestRegion::ResizeRight: cmd = HTRIGHT; break;
217
+ case HitTestRegion::ResizeTopLeft: cmd = HTTOPLEFT; break;
218
+ case HitTestRegion::ResizeTopRight: cmd = HTTOPRIGHT; break;
219
+ case HitTestRegion::ResizeBottomLeft: cmd = HTBOTTOMLEFT; break;
220
+ case HitTestRegion::ResizeBottomRight: cmd = HTBOTTOMRIGHT; break;
221
+ default: return;
222
+ }
223
+ SendMessage(hwnd_, WM_NCLBUTTONDOWN, cmd, 0);
224
+ }
225
+
226
+ HitTestRegion Win32Window::hit_test(Point cursor) {
227
+ if (config_.on_hit_test) {
228
+ return config_.on_hit_test(cursor);
229
+ }
230
+ Size win_size = size();
231
+ int w = win_size.width;
232
+ int h = win_size.height;
233
+ int b = config_.resize_border_width;
234
+
235
+ bool at_left = cursor.x < b;
236
+ bool at_right = cursor.x >= w - b;
237
+ bool at_top = cursor.y < b;
238
+ bool at_bottom = cursor.y >= h - b;
239
+
240
+ if (config_.resizable) {
241
+ if (at_top && at_left) return HitTestRegion::ResizeTopLeft;
242
+ if (at_top && at_right) return HitTestRegion::ResizeTopRight;
243
+ if (at_bottom && at_left) return HitTestRegion::ResizeBottomLeft;
244
+ if (at_bottom && at_right) return HitTestRegion::ResizeBottomRight;
245
+ if (at_top) return HitTestRegion::ResizeTop;
246
+ if (at_bottom) return HitTestRegion::ResizeBottom;
247
+ if (at_left) return HitTestRegion::ResizeLeft;
248
+ if (at_right) return HitTestRegion::ResizeRight;
249
+ }
250
+
251
+ if (cursor.y < config_.caption_height) {
252
+ return HitTestRegion::Caption;
253
+ }
254
+ return HitTestRegion::Client;
255
+ }
256
+
257
+ void Win32Window::resize_webview(int w, int h) {
258
+ if (webview_) {
259
+ webview_->resize(w, h);
260
+ }
261
+ }
262
+
263
+ Win32Window* Win32Window::from_hwnd(HWND hwnd) {
264
+ return reinterpret_cast<Win32Window*>(GetPropW(hwnd, kWindowPPProp));
265
+ }
266
+
267
+ } // namespace wpp
@@ -0,0 +1,79 @@
1
+ // ============================================================================
2
+ // window_win32.h — Win32 Window implementation
3
+ // ============================================================================
4
+
5
+ #pragma once
6
+
7
+ #define WIN32_LEAN_AND_MEAN
8
+ #define NOMINMAX
9
+ #include <windows.h>
10
+ #include <dwmapi.h>
11
+ #include <map>
12
+ #include <functional>
13
+ #include <memory>
14
+ #include "win32_helpers.h"
15
+ #include <windowpp/windowpp.h>
16
+
17
+ namespace wpp {
18
+
19
+ class Win32Window : public Window {
20
+ public:
21
+ Win32Window(const WindowConfig& config, HWND hwnd);
22
+ ~Win32Window() override;
23
+
24
+ std::string id() const override { return config_.id; }
25
+ std::string title() const override;
26
+ Size size() const override;
27
+ Point position() const override;
28
+ WindowState state() const override;
29
+ bool is_visible() const override;
30
+ bool is_focused() const override;
31
+ float scale_factor() const override;
32
+ void* native_handle() const override { return hwnd_; }
33
+
34
+ void set_title(const std::string& title) override;
35
+ void set_size(int w, int h) override;
36
+ void set_position(int x, int y) override;
37
+ void set_min_size(int w, int h) override;
38
+ void set_max_size(int w, int h) override;
39
+ void set_resizable(bool v) override;
40
+ void set_always_on_top(bool v) override;
41
+ void set_opacity(float v) override;
42
+ void set_background(Color c) override;
43
+ void set_cursor(CursorType c) override;
44
+
45
+ void show() override;
46
+ void hide() override;
47
+ void close() override;
48
+ void focus() override;
49
+ void minimize() override;
50
+ void maximize() override;
51
+ void restore() override;
52
+ void fullscreen() override;
53
+ void center() override;
54
+ void request_repaint() override;
55
+ void start_drag() override;
56
+ void start_resize(HitTestRegion edge) override;
57
+
58
+ WebView* webview() override { return webview_.get(); }
59
+ void set_webview(std::unique_ptr<WebView> wv) { webview_ = std::move(wv); }
60
+ void resize_webview(int w, int h);
61
+
62
+ HWND hwnd() const { return hwnd_; }
63
+ const WindowConfig& config() const { return config_; }
64
+ void nullify_hwnd() { hwnd_ = nullptr; }
65
+
66
+ HitTestRegion hit_test(Point cursor);
67
+
68
+ static Win32Window* from_hwnd(HWND hwnd);
69
+
70
+ private:
71
+ WindowConfig config_;
72
+ HWND hwnd_;
73
+ bool is_tracking_mouse_ = false;
74
+ std::map<uint64_t, std::function<void()>> timers_;
75
+ uint64_t next_timer_id_ = 1;
76
+ std::unique_ptr<WebView> webview_;
77
+ };
78
+
79
+ } // namespace wpp
@@ -0,0 +1,128 @@
1
+ // ============================================================================
2
+ // WindowPP — WebGPU Renderer Integration
3
+ // File: src/renderer/webgpu.h
4
+ //
5
+ // Cross-platform WebGPU surface creation from a native WindowPP handle.
6
+ // Works on Windows (HWND), macOS (NSWindow → CAMetalLayer), Linux (X11).
7
+ //
8
+ // Backend options (link one):
9
+ // • Dawn — https://dawn.googlesource.com/dawn (Google / C++)
10
+ // • wgpu — https://github.com/gfx-rs/wgpu-native (Rust / C bindings)
11
+ //
12
+ // Usage:
13
+ // #include <windowpp/windowpp.h>
14
+ // #include <renderer/webgpu.h>
15
+ //
16
+ // WGPUInstance instance = wgpuCreateInstance(nullptr);
17
+ // WGPUSurface surface = wpp::renderer::create_webgpu_surface(instance,
18
+ // window->native_handle());
19
+ //
20
+ // Works standalone in any wpp::Window — no WebView required.
21
+ // Also usable inside a WebView if the WebView exposes a native GPU surface.
22
+ // ============================================================================
23
+
24
+ #pragma once
25
+
26
+ #include <webgpu/webgpu.h>
27
+
28
+ // ── Platform headers ─────────────────────────────────────────────────────────
29
+
30
+ #if defined(_WIN32)
31
+ # ifndef WIN32_LEAN_AND_MEAN
32
+ # define WIN32_LEAN_AND_MEAN
33
+ # endif
34
+ # ifndef NOMINMAX
35
+ # define NOMINMAX
36
+ # endif
37
+ # include <windows.h>
38
+
39
+ #elif defined(__APPLE__)
40
+ # include <objc/runtime.h>
41
+ # include <objc/message.h>
42
+
43
+ #elif defined(__linux__)
44
+ # include <X11/Xlib.h>
45
+ # include <cstdint>
46
+ #endif
47
+
48
+ namespace wpp {
49
+ namespace renderer {
50
+
51
+ // ── Surface creation ─────────────────────────────────────────────────────────
52
+
53
+ // Creates a WGPUSurface for the given native window handle.
54
+ //
55
+ // Pass the value returned by wpp::Window::native_handle():
56
+ // Windows → HWND
57
+ // macOS → NSWindow*
58
+ // Linux → X11 Window (cast to void*)
59
+ //
60
+ // On Linux the X11 Display is opened automatically via XOpenDisplay(nullptr).
61
+ // If you manage the Display yourself, use create_webgpu_surface_x11() below.
62
+
63
+ inline WGPUSurface create_webgpu_surface(WGPUInstance instance, void* native_handle) {
64
+ #if defined(_WIN32)
65
+
66
+ WGPUSurfaceDescriptorFromWindowsHWND platform = {};
67
+ platform.chain.sType = WGPUSType_SurfaceDescriptorFromWindowsHWND;
68
+ platform.hinstance = GetModuleHandleW(nullptr);
69
+ platform.hwnd = native_handle;
70
+
71
+ WGPUSurfaceDescriptor desc = {};
72
+ desc.nextInChain = reinterpret_cast<WGPUChainedStruct*>(&platform);
73
+ return wgpuInstanceCreateSurface(instance, &desc);
74
+
75
+ #elif defined(__APPLE__)
76
+
77
+ // native_handle is NSWindow* — extract the CAMetalLayer from its contentView
78
+ id ns_window = reinterpret_cast<id>(native_handle);
79
+ id content_view = reinterpret_cast<id(*)(id, SEL)>(objc_msgSend)(
80
+ ns_window, sel_registerName("contentView"));
81
+ id metal_layer = reinterpret_cast<id(*)(id, SEL)>(objc_msgSend)(
82
+ content_view, sel_registerName("layer"));
83
+
84
+ WGPUSurfaceDescriptorFromMetalLayer platform = {};
85
+ platform.chain.sType = WGPUSType_SurfaceDescriptorFromMetalLayer;
86
+ platform.layer = metal_layer;
87
+
88
+ WGPUSurfaceDescriptor desc = {};
89
+ desc.nextInChain = reinterpret_cast<WGPUChainedStruct*>(&platform);
90
+ return wgpuInstanceCreateSurface(instance, &desc);
91
+
92
+ #elif defined(__linux__)
93
+
94
+ Display* display = XOpenDisplay(nullptr);
95
+ return create_webgpu_surface_x11(instance, display, native_handle, false);
96
+
97
+ #else
98
+ (void)instance; (void)native_handle;
99
+ return nullptr;
100
+ #endif
101
+ }
102
+
103
+ // ── Linux: explicit Display overload ────────────────────────────────────────
104
+
105
+ #if defined(__linux__)
106
+ // Use this variant when you already hold an X11 Display* (avoids opening
107
+ // a second connection). Set owns_display=true to have it closed for you.
108
+ inline WGPUSurface create_webgpu_surface_x11(WGPUInstance instance,
109
+ Display* display,
110
+ void* native_handle,
111
+ bool owns_display = false) {
112
+ WGPUSurfaceDescriptorFromXlibWindow platform = {};
113
+ platform.chain.sType = WGPUSType_SurfaceDescriptorFromXlibWindow;
114
+ platform.display = display;
115
+ platform.window = static_cast<uint32_t>(
116
+ reinterpret_cast<uintptr_t>(native_handle));
117
+
118
+ WGPUSurfaceDescriptor desc = {};
119
+ desc.nextInChain = reinterpret_cast<WGPUChainedStruct*>(&platform);
120
+ WGPUSurface surface = wgpuInstanceCreateSurface(instance, &desc);
121
+
122
+ if (owns_display && display) XCloseDisplay(display);
123
+ return surface;
124
+ }
125
+ #endif
126
+
127
+ } // namespace renderer
128
+ } // namespace wpp