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,388 @@
1
+ // ============================================================================
2
+ // webview_macos.mm — macOS WKWebView implementation
3
+ // ============================================================================
4
+
5
+ #if defined(__APPLE__)
6
+
7
+ #import <WebKit/WebKit.h>
8
+ #include <memory>
9
+ #include <string>
10
+
11
+ // ─────────────────────────────────────────────────────────────────────────────
12
+ // PWSchemeHandler — WKURLSchemeHandler that serves embedded assets.
13
+ // Stores a copy of the C++ scheme_handler std::function as an Objective-C ivar.
14
+ // ─────────────────────────────────────────────────────────────────────────────
15
+ @interface PWSchemeHandler : NSObject <WKURLSchemeHandler>
16
+ @end
17
+
18
+ @implementation PWSchemeHandler {
19
+ std::function<wpp::SchemeResponse(const std::string&)> _handler;
20
+ }
21
+
22
+ - (instancetype)initWithHandlerFunc:
23
+ (std::function<wpp::SchemeResponse(const std::string&)>)handler {
24
+ self = [super init];
25
+ if (self) _handler = handler;
26
+ return self;
27
+ }
28
+
29
+ - (void)webView:(WKWebView*)webView
30
+ startURLSchemeTask:(id<WKURLSchemeTask>)urlSchemeTask {
31
+ const char* rawPath =
32
+ urlSchemeTask.request.URL.path.UTF8String;
33
+ std::string path(rawPath ? rawPath : "/");
34
+ if (path.empty()) path = "/";
35
+
36
+ wpp::SchemeResponse resp = _handler(path);
37
+
38
+ NSData* body = [NSData dataWithBytes:resp.body.data()
39
+ length:resp.body.size()];
40
+ NSString* mimeType = [NSString stringWithUTF8String:resp.content_type.c_str()];
41
+
42
+ NSURLResponse* response =
43
+ [[NSURLResponse alloc] initWithURL:urlSchemeTask.request.URL
44
+ MIMEType:mimeType
45
+ expectedContentLength:(NSInteger)resp.body.size()
46
+ textEncodingName:nil];
47
+ [urlSchemeTask didReceiveResponse:response];
48
+ [urlSchemeTask didReceiveData:body];
49
+ [urlSchemeTask didFinish];
50
+ }
51
+
52
+ - (void)webView:(WKWebView*)webView
53
+ stopURLSchemeTask:(id<WKURLSchemeTask>)urlSchemeTask {
54
+ // Synchronous handler — nothing to cancel.
55
+ }
56
+
57
+ @end
58
+
59
+ namespace wpp {
60
+
61
+ namespace {
62
+
63
+ NSString* wpp_dropzone_toggle_script(bool enabled) {
64
+ return enabled
65
+ ? @"window.__wpp_dropzone_enabled = true;"
66
+ : @"window.__wpp_dropzone_enabled = false; document.querySelectorAll('.wpp-dropzone-active').forEach(function(el){ el.classList.remove('wpp-dropzone-active'); });";
67
+ }
68
+
69
+ NSString* wpp_dropzone_script() {
70
+ return @R"JS(
71
+ (function() {
72
+ if (window.__wpp_dropzone_init) return;
73
+ window.__wpp_dropzone_init = true;
74
+ window.__wpp_dropzone_enabled = true;
75
+
76
+ var activeZone = null;
77
+ var pendingZone = null;
78
+ var cachedZones = [];
79
+ var outerBounds = null;
80
+ var refreshPending = false;
81
+ var framePending = false;
82
+ var _lastHit = null;
83
+ var observedZones = [];
84
+ var resizeObserver = typeof ResizeObserver === 'function'
85
+ ? new ResizeObserver(function() { scheduleRefreshZones(); })
86
+ : null;
87
+
88
+ var disconnectObservedZones = function() {
89
+ if (!resizeObserver) return;
90
+ for (var i = 0; i < observedZones.length; i++) {
91
+ resizeObserver.unobserve(observedZones[i]);
92
+ }
93
+ observedZones = [];
94
+ };
95
+
96
+ var refreshZones = function() {
97
+ refreshPending = false;
98
+ _lastHit = null;
99
+ disconnectObservedZones();
100
+ cachedZones = [];
101
+ outerBounds = null;
102
+ var zones = document.querySelectorAll('[data-dropzone]');
103
+ for (var i = 0; i < zones.length; i++) {
104
+ var zone = zones[i];
105
+ var rect = zone.getBoundingClientRect();
106
+ var zoneData = {
107
+ element: zone,
108
+ left: rect.left,
109
+ top: rect.top,
110
+ right: rect.right,
111
+ bottom: rect.bottom
112
+ };
113
+ cachedZones.push(zoneData);
114
+ if (resizeObserver) {
115
+ resizeObserver.observe(zone);
116
+ observedZones.push(zone);
117
+ }
118
+ if (!outerBounds) {
119
+ outerBounds = {left: rect.left, top: rect.top, right: rect.right, bottom: rect.bottom};
120
+ } else {
121
+ outerBounds.left = Math.min(outerBounds.left, rect.left);
122
+ outerBounds.top = Math.min(outerBounds.top, rect.top);
123
+ outerBounds.right = Math.max(outerBounds.right, rect.right);
124
+ outerBounds.bottom = Math.max(outerBounds.bottom, rect.bottom);
125
+ }
126
+ }
127
+ };
128
+
129
+ var scheduleRefreshZones = function() {
130
+ if (refreshPending) return;
131
+ refreshPending = true;
132
+ window.requestAnimationFrame(refreshZones);
133
+ };
134
+
135
+ var findDropZoneAt = function(x, y) {
136
+ if (!outerBounds || x < outerBounds.left || x > outerBounds.right || y < outerBounds.top || y > outerBounds.bottom) {
137
+ return null;
138
+ }
139
+ if (_lastHit && x >= _lastHit.left && x <= _lastHit.right && y >= _lastHit.top && y <= _lastHit.bottom) {
140
+ return _lastHit.element;
141
+ }
142
+ for (var i = cachedZones.length - 1; i >= 0; i--) {
143
+ var zone = cachedZones[i];
144
+ if (x >= zone.left && x <= zone.right && y >= zone.top && y <= zone.bottom) {
145
+ _lastHit = zone;
146
+ return zone.element;
147
+ }
148
+ }
149
+ _lastHit = null;
150
+ return null;
151
+ };
152
+
153
+ var updateActiveZone = function(zone) {
154
+ if (activeZone === zone) return;
155
+ if (activeZone) {
156
+ activeZone.classList.remove('wpp-dropzone-active');
157
+ }
158
+ activeZone = zone;
159
+ if (activeZone) {
160
+ activeZone.classList.add('wpp-dropzone-active');
161
+ }
162
+ };
163
+
164
+ var flushActiveZone = function() {
165
+ framePending = false;
166
+ updateActiveZone(window.__wpp_dropzone_enabled ? pendingZone : null);
167
+ };
168
+
169
+ var scheduleZoneUpdate = function(zone) {
170
+ pendingZone = zone;
171
+ if (framePending) return;
172
+ framePending = true;
173
+ window.requestAnimationFrame(flushActiveZone);
174
+ };
175
+
176
+ var setDropEffect = function(e, zone) {
177
+ if (!e.dataTransfer) return;
178
+ try {
179
+ e.dataTransfer.dropEffect = zone ? 'copy' : 'none';
180
+ } catch (_) {}
181
+ };
182
+
183
+ document.addEventListener('dragenter', function(e) {
184
+ if (!window.__wpp_dropzone_enabled) return;
185
+ e.preventDefault();
186
+ if (!cachedZones.length) refreshZones();
187
+ var zone = findDropZoneAt(e.clientX, e.clientY);
188
+ setDropEffect(e, zone);
189
+ scheduleZoneUpdate(zone);
190
+ }, true);
191
+
192
+ document.addEventListener('dragover', function(e) {
193
+ if (!window.__wpp_dropzone_enabled) return;
194
+ e.preventDefault();
195
+ var zone = findDropZoneAt(e.clientX, e.clientY);
196
+ setDropEffect(e, zone);
197
+ scheduleZoneUpdate(zone);
198
+ }, true);
199
+
200
+ document.addEventListener('dragleave', function(e) {
201
+ if (!window.__wpp_dropzone_enabled) return;
202
+ e.preventDefault();
203
+ var related = e.relatedTarget;
204
+ if (!related || related === document.documentElement || related === document.body) {
205
+ pendingZone = null;
206
+ framePending = false;
207
+ _lastHit = null;
208
+ updateActiveZone(null);
209
+ }
210
+ }, true);
211
+
212
+ document.addEventListener('drop', function(e) {
213
+ if (!window.__wpp_dropzone_enabled) return;
214
+ e.preventDefault();
215
+ pendingZone = null;
216
+ framePending = false;
217
+ var zone = findDropZoneAt(e.clientX, e.clientY);
218
+ var zoneName = zone ? zone.getAttribute('data-dropzone') : null;
219
+ _lastHit = null;
220
+ updateActiveZone(null);
221
+
222
+ if (zoneName && window.__wpp_fileDrop__) {
223
+ var files = [];
224
+ if (e.dataTransfer && e.dataTransfer.files) {
225
+ for (var i = 0; i < e.dataTransfer.files.length; i++) {
226
+ var file = e.dataTransfer.files[i];
227
+ files.push({
228
+ name: file.name,
229
+ size: file.size,
230
+ type: file.type || 'application/octet-stream'
231
+ });
232
+ }
233
+ }
234
+ window.__wpp_fileDrop__(zoneName, files);
235
+ }
236
+ }, true);
237
+ window.addEventListener('dragover', function(e) {
238
+ if (!window.__wpp_dropzone_enabled) return;
239
+ e.preventDefault();
240
+ setDropEffect(e, findDropZoneAt(e.clientX, e.clientY));
241
+ }, true);
242
+ window.addEventListener('drop', function(e) {
243
+ if (!window.__wpp_dropzone_enabled) return;
244
+ e.preventDefault();
245
+ }, true);
246
+ window.addEventListener('resize', scheduleRefreshZones, true);
247
+ window.addEventListener('scroll', scheduleRefreshZones, true);
248
+ document.addEventListener('DOMContentLoaded', scheduleRefreshZones, true);
249
+ window.addEventListener('load', scheduleRefreshZones, true);
250
+ var attachMutationObserver = function() {
251
+ if (typeof MutationObserver !== 'function') return;
252
+ var target = document.documentElement || document.body;
253
+ if (!target || typeof target.nodeType !== 'number') return;
254
+ new MutationObserver(scheduleRefreshZones).observe(
255
+ target,
256
+ { childList: true, subtree: true, attributes: true, attributeFilter: ['data-dropzone'] }
257
+ );
258
+ };
259
+ if (typeof MutationObserver === 'function') {
260
+ attachMutationObserver();
261
+ document.addEventListener('DOMContentLoaded', attachMutationObserver, { once: true });
262
+ window.addEventListener('load', attachMutationObserver, { once: true });
263
+ }
264
+ refreshZones();
265
+ })();
266
+ )JS";
267
+ }
268
+
269
+ } // namespace
270
+
271
+ class MacOSWebView : public WebView {
272
+ public:
273
+ MacOSWebView(const WebViewConfig& config, NSWindow* window);
274
+ ~MacOSWebView() override;
275
+
276
+ void load_url(const std::string& url) override;
277
+ void load_html(const std::string& html) override;
278
+ void execute_script(const std::string& script) override;
279
+ void send_message(const std::string& message) override;
280
+ void go_back() override;
281
+ void go_forward() override;
282
+ void reload() override;
283
+ void close() override;
284
+ void resize(int width, int height) override {
285
+ // macOS WebView auto-resizes via autoresizingMask
286
+ }
287
+
288
+ void set_drag_drop_enabled(bool enabled) override {
289
+ if (!webview_) return;
290
+ [webview_ evaluateJavaScript:wpp_dropzone_toggle_script(enabled) completionHandler:nil];
291
+ }
292
+
293
+ private:
294
+ WebViewConfig config_;
295
+ NSWindow* window_;
296
+ WKWebView* webview_ = nullptr;
297
+ };
298
+
299
+ MacOSWebView::MacOSWebView(const WebViewConfig& config, NSWindow* window)
300
+ : config_(config), window_(window) {
301
+
302
+ WKWebViewConfiguration* wkConfig = [[WKWebViewConfiguration alloc] init];
303
+ wkConfig.websiteDataStore = [WKWebsiteDataStore defaultDataStore];
304
+ WKUserContentController* contentController = [[WKUserContentController alloc] init];
305
+ WKUserScript* dropzoneUserScript = [[WKUserScript alloc]
306
+ initWithSource:wpp_dropzone_script()
307
+ injectionTime:WKUserScriptInjectionTimeAtDocumentStart
308
+ forMainFrameOnly:NO];
309
+ [contentController addUserScript:dropzoneUserScript];
310
+ wkConfig.userContentController = contentController;
311
+
312
+ if (!config.custom_scheme.empty() && config.scheme_handler) {
313
+ NSString* scheme =
314
+ [NSString stringWithUTF8String:config.custom_scheme.c_str()];
315
+ PWSchemeHandler* handler =
316
+ [[PWSchemeHandler alloc] initWithHandlerFunc:config.scheme_handler];
317
+ [wkConfig setURLSchemeHandler:handler forURLScheme:scheme];
318
+ }
319
+
320
+ webview_ = [[WKWebView alloc] initWithFrame:window.contentView.bounds
321
+ configuration:wkConfig];
322
+ webview_.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
323
+ [window.contentView addSubview:webview_];
324
+
325
+ if (!config_.initial_url.empty()) {
326
+ load_url(config_.initial_url);
327
+ } else if (!config_.initial_html.empty()) {
328
+ load_html(config_.initial_html);
329
+ }
330
+ }
331
+
332
+ MacOSWebView::~MacOSWebView() {
333
+ if (webview_) {
334
+ [webview_ removeFromSuperview];
335
+ }
336
+ }
337
+
338
+ void MacOSWebView::load_url(const std::string& url) {
339
+ if (!webview_) return;
340
+ NSURL* nsurl = [NSURL URLWithString:[NSString stringWithUTF8String:url.c_str()]];
341
+ if (nsurl) {
342
+ [webview_ loadRequest:[NSURLRequest requestWithURL:nsurl]];
343
+ }
344
+ }
345
+
346
+ void MacOSWebView::load_html(const std::string& html) {
347
+ if (!webview_) return;
348
+ [webview_ loadHTMLString:[NSString stringWithUTF8String:html.c_str()] baseURL:nil];
349
+ }
350
+
351
+ void MacOSWebView::execute_script(const std::string& script) {
352
+ if (!webview_) return;
353
+ NSString* js = [NSString stringWithUTF8String:script.c_str()];
354
+ [webview_ evaluateJavaScript:js completionHandler:nil];
355
+ }
356
+
357
+ void MacOSWebView::send_message(const std::string& message) {
358
+ if (!webview_) return;
359
+ NSString* js = [NSString stringWithFormat:@"window.webkit.messageHandlers.wpp.postMessage('%s');", message.c_str()];
360
+ [webview_ evaluateJavaScript:js completionHandler:nil];
361
+ }
362
+
363
+ void MacOSWebView::go_back() {
364
+ if (webview_) [webview_ goBack];
365
+ }
366
+
367
+ void MacOSWebView::go_forward() {
368
+ if (webview_) [webview_ goForward];
369
+ }
370
+
371
+ void MacOSWebView::reload() {
372
+ if (webview_) [webview_ reload];
373
+ }
374
+
375
+ void MacOSWebView::close() {
376
+ if (webview_) {
377
+ [webview_ removeFromSuperview];
378
+ webview_ = nil;
379
+ }
380
+ }
381
+
382
+ std::unique_ptr<WebView> create_webview(const WebViewConfig& config, void* native_handle) {
383
+ return std::make_unique<MacOSWebView>(config, (__bridge NSWindow*)native_handle);
384
+ }
385
+
386
+ } // namespace wpp
387
+
388
+ #endif // __APPLE__